User Tools

Site Tools


php:state

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

php:state [2013/03/16 17:40] (current)
Line 1: Line 1:
 +=== STATE PATTERN ===
 +30.03.2010
 +
 +
 +The State pattern allows an object to change its behavior when its internal state changes. Basically the states are kept in a separate object that encapsulates the state-related behavior. The switch constructions are often candidates for this pattern.
 +
 +
 +<columns 100% first column attributes 50% second column attributes 50%>
 +{{:​php:​statepattern.png| State Pattern Diagram}}
 +<​newcolumn>​
 +Participants:​
 +
 +    * Context: defines an interface for Clients and maintains a State object internally.
 +    * State: defines an interface for the state-related behavior and often for transitions.
 +    * ConcreteState (more than one class): implements a particular behavior and set of valid transitions.
 +
 +The State pattern __does not specify__ where the state transitions will be defined. The choices are two: the **context** object, or **each individual State derived class**. The advantage of the later option is ease of adding new State derived classes. The disadvantage is each State derived class has knowledge of (coupling to) its siblings, which introduces dependencies between subclasses.
 +</​columns>​
 +
 +
 +We get the example of a Printer with 4 identified states: ready, print starting, printing (in progress), print ending. \\ 
 +Each state class will have an //​action()//​ method and an (optionally) //​display_state()//​ method (used to better debug the operations). \\ 
 +**States classes** will look as:
 +
 +<code php>
 +// State interface here
 +interface PrinterState {
 +    public function display_state();​
 +    public function action();
 +
 +}
 +
 +// Concrete States classes follow
 +class StateReady implements PrinterState {
 +    public function action() {
 +        echo "​Printer is ready.\n";​
 +        return new StatePrintStart;​
 +    }
 +    ​
 +    public function display_state() { echo get_class($this)."​->";​ }
 +}
 +
 +class StatePrintStart implements PrinterState {
 +    public function action() {
 +        echo "The print is starting.\n";​
 +        return new StatePrinting; ​   ​
 +    }
 +
 +    public function display_state() { echo get_class($this)."​->";​ }
 +}
 +
 +class StatePrinting implements PrinterState {
 +   
 +    public function action() {
 +        echo "​Printer is printing nicely.\n";​
 +        return new StatePrintEnd;​
 +    }
 +    ​
 +    public function display_state() { echo get_class($this)."​->";​ }
 +}
 +
 +class StatePrintEnd implements PrinterState {
 +    ​
 +    public function action() {
 +        echo "​Printer has finish its job.\n";​
 +        return new StateReady;
 +    }
 +    ​
 +    public function display_state() { echo get_class($this)."​->";​ }
 +}
 +</​code>​
 +
 +
 +After this, the **interface class**:
 +
 +<code php>
 +class Printer {
 +    protected $_printerstate;​
 +
 +    /**
 +     * @param State $initialState ​  the state at the start
 +     */
 +    public function __construct(PrinterState $initialState) {
 +        $this->​_printerstate = $initialState;​
 +    }
 +
 +    public function run() {
 +        $this->​_printerstate->​display_state();​ // just for displaying purposes
 +        $this->​_printerstate = $this->​_printerstate->​action();​ // each action returns next possible state
 +    }
 +    ​
 +    public function cancel() {
 +        // simplified example
 +        // this will call the end state no matter what and after end action, prepare again the printer
 +        $endstate = new StatePrintEnd;​
 +        $this->​_printerstate = $endstate->​action();​
 +    }
 +}
 +</​code>​
 +
 +Then **run the code**:
 +
 +<code php>
 +$printer = new Printer(new StateReady);​
 +
 +echo "​---------------------- \n";
 +$printer->​run();​ // the printer becomes ready
 +echo "​---------------------- \n";
 +$printer->​cancel();​ // here we cancel
 +echo "​---------------------- \n";
 +$printer->​run();​ // return and retry again
 +echo "​---------------------- \n";
 +$printer->​run();​
 +echo "​---------------------- \n";
 +$printer->​run();​
 +echo "​---------------------- \n";
 +$printer->​run();​
 +echo "​---------------------- \n";
 +</​code>​
 +
 +**Result** for above code is:
 +
 +<​code>​
 +...$> php state_pattern.php ​
 +---------------------- ​
 +StateReady->​Printer is ready.
 +---------------------- ​
 +Printer has finish its job.
 +---------------------- ​
 +StateReady->​Printer is ready.
 +---------------------- ​
 +StatePrintStart->​The print is starting.
 +---------------------- ​
 +StatePrinting->​Printer is printing nicely.
 +---------------------- ​
 +StatePrintEnd->​Printer has finish its job.
 +---------------------- ​
 +
 +</​code>​
 +
 +
 +**References:​**
 +
 +[[http://​www.ibm.com/​developerworks/​opensource/​library/​os-php-designpatterns/#​N101EE|Robot example]] \\ 
 +[[http://​giorgiosironi.blogspot.com/​2010/​03/​practical-php-patterns-state.html|Giorgio Sironi example]] \\ 
 +[[http://​sourcemaking.com/​design_patterns/​state|Page about State Pattern]] \\ 
 +
  
php/state.txt ยท Last modified: 2013/03/16 17:40 (external edit)