Разница между стратегией и шаблоном проектирования государства. Как государство узнает о своем предшественнике?

Я читал о шаблонах проектирования состояния и стратегии на веб-сайте refactoring.guru на страницах Состояние и Стратегия . Автор говорит

Эта структура может выглядеть похожей на шаблон «Стратегия», но есть одно ключевое отличие. В шаблоне State отдельные состояния могут знать друг о друге и инициировать переходы из одного состояния в другое, тогда как стратегии почти никогда не знают друг о друге.

Автор также говорит, что классы ConcereteState хранят переменную context, которая является объектом класса Context, и с помощью этой переменной состояния могут узнавать друг о друге.

Я не могу понять две вещи:

  1. Как государство знает о своем предшественнике?
  2. Где мне реализовать логику перехода между состояниями? Например state1 по вводу a переходит в state2 а по b переходит в state4, где именно должна быть реализована эта логика?

Это простая реализация стратегии, которую я реализовал на языке php.

<?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();

и это простая реализация шаблона проектирования State, который я реализовал

<?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();

?>

Я не вижу большой разницы между состоянием и стратегией, хотя я точно знаю, каковы цели этих стратегий. Кроме того, в коде отсутствует логика перемещения между состояниями и то, как состояние должно знать своего родителя.


person M a m a D    schedule 31.12.2018    source источник


Ответы (1)


Из ваших примеров эти два шаблона выглядят очень похожими. Но ваш пример шаблона проектирования состояния на самом деле не является шаблоном проектирования состояния, потому что вы устанавливаете состояние извне. Типичный шаблон проектирования состояния изменяет состояние внутри и очень часто делегирует изменение самому состоянию. Давайте посмотрим на простую кнопку-переключатель. У него есть состояние, метод нажатия и метод описания текущего состояния (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;
    }
}

Таким образом, извне вы не устанавливаете состояние, поэтому вы не знаете, в каком состоянии оно находится и как оно будет реагировать. Ты используешь:

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

Таким образом, ключевое отличие состоит в том, что для стратегии вы передаете стратегию извне и позволяете вашему объекту выполнять некоторую операцию (которая не меняет стратегию), поэтому это липкое делегирование.

Но цель шаблона проектирования State состоит в том, что состояние должно изменяться, очень часто внутренне, а с изменением состояния меняется и поведение. Таким образом, даже если мы установим некоторое состояние перед вычислением какой-либо задачи, оно может измениться (обычно изменяется) внутри во время выполнения задачи для ее завершения. Это способ достижения полиморфизма состояния. Также обратите внимание, что это часто связано с автоматами состояний.

person Ondřej Fischer    schedule 01.01.2019