简体   繁体   中英

The difference between strategy and state design patterm, How a state is aware of its predecessor?

I read about state and strategy design patterns in refactoring.guru web site in pages State and Strategy . The author says

This structure may look similar to the Strategy pattern, but there's one key difference. In the State pattern, the particular states may be aware of each other and initiate transitions from one state to another, whereas strategies almost never know about each other.

The author also says, the ConcereteState classes, store a variable context which is an object to Context class and by this variable, states may aware of each other.

There are two things I can't understand:

  1. How a state is aware of its predecessor?
  2. Where should I implement the logic of transition between states? For example state1 by input a moves to state2 and by b moves to state4 , where exactly this logic must be implemented?

This is a simple implementation of strategy I implemented in php language

<?php
class Algorithms{
    public $algorithm;
    function __construct(AlgorithmsInterface $algorithm){
        $this->algorithm = $algorithm;
    }

    public function run(){
        $this->algorithm->run();
    }
}

interface AlgorithmsInterface{      
    public function run();
}

class Algorithm1 implements AlgorithmsInterface{
    public function run(){
        print "Algorithm1";
    }
}

class Algorithm2 implements AlgorithmsInterface{
    public function run(){
        print "Algorithm2";
    }
}


$payment = new Algorithms(new Algorithm2());
$payment->run();

and this is a simple implementation of State design pattern I implemented

<?php
    interface State{
        public function execute();
    }

    class Context{

        public $state;

        public function __construct(State $initialState){
            $this->state = $initialState;
        }

        public function changeState(State $state){
            $this->state = $state;
        }

        public function execute(){
            $this->state->execute();
        }
    }

    class State1 implements State{
        public function execute(){
            print "This is State1";
        }
    }

    class State2 implements State{
        public function execute(){
            print "This is State2";
        }
    }

    $initialState = new State1();
    $state2 = new State2();
    $context = new Context($initialState);
    $context->execute();
    $context->changeState($state2);
    $context->execute();

?>

I can't see much difference between state and strategy while I know exactly what the intents of these strategies are . Besides that, the logic of movement between states and the way a state should be aware of its parent are missed from the code.

From your examples the two patterns look very similar. But your example of State design pattern is not really state design pattern, because you are setting the state from outside. Typical state design pattern changes state internally and very often delegates the change to the state itself. Let's look at simple toggle button. It has a state, and method to press it, and method to describe current state ( toString() ):

class ToggleButton {
    enum State {
        ON {
            public State press() {
                return OFF;
            }
         },
         OFF {
             public State press() {
                 return ON;
             }
         };
         abstract public State press();
    }

    State state = State.OFF;
    public void press() {
        state = state.press();
    }
    public String toString() {
        return "Device is " + state;
    }
}

So from outside you're not setting the state, so you don't know in which state it is and how it will react. You use:

button.press();
System.out.println(button);

So the key difference is, that for strategy, you pass the strategy from outside, and let your object perform some operation (which doesn't change the strategy), so it's sticky delegation.

But purpose of State design pattern is, that the state is supposed to change, very often intrrnally, and with change of the state also the behavior changes. So even if we set some state before computation of some task, it may change (typically does) internally during the task to complete it. It's a way to achieve state polymorphism. Also notice, that it's often related to state automata.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM