Я понимаю, что State pattern
может использоваться для моделирования объектов, которые изменяют поведение в зависимости от состояния, и различные состояния, которые может иметь Context
, инкапсулируются в конкретные классы, которые представляют интерфейс State
. Что мне не ясно, так это то, как переходы между состояниями происходят в этом шаблоне. Знает ли человек states
и решает ли он, кто следует за ним, или Context
решает, какое состояние он получит в следующий раз?
Кто определяет переходы между состояниями в шаблоне состояний?
Ответы (2)
Из книги «Шаблоны проектирования GOF» (находится в разделе «Реализация»):
1. Кто определяет переходы между состояниями? В шаблоне состояния не указывается, какой участник определяет критерии для переходов между состояниями. Если критерии фиксированы, то они могут быть полностью реализованы в контексте. Однако, как правило, более гибко и уместно позволить подклассам State самим определять свое состояние-преемник и время выполнения перехода. Для этого требуется добавить интерфейс в контекст, который позволяет объектам состояния явно устанавливать текущее состояние контекста.
Децентрализация логики перехода таким образом упрощает изменение или расширение логики путем определения новых подклассов состояния. Недостатком децентрализации является то, что один подкласс State будет знать по крайней мере об одном другом, что вводит зависимости реализации между подклассами.
Может быть, относительно конкретный пример может прояснить. Надеюсь я правильно это понимаю
Предположим, стиральная машина находится в двух состояниях (ВКЛ., ВЫКЛ.). После словаря GoF:
- Контекст => Стиральная машина
- Состояние => Состояние стиральной машины
- Конкретные состояния => StateOn, StateOff
Для перехода между состояниями через подклассы состояния (в нашем случае StateOn и StateOff) нам нужен метод для изменения состояния Context:
class WashingMachine {
WashingMachineState state;
...
protected void setState(WashingMachineState newState) {
state = newState;
}
someMethod () {
...
state.pushStartButton(this);
...
}
}
abstract class WashingMachineState {
protected void run();
protected void pushStartButton(WashingMachine wm);
}
class StateOn extends WashingMachineState {
...
void pushStartButton(WashingMachine wm) {
wm.setState(new StateOff())
}
}
class StateOff extends WashingMachineState {
...
void pushStartButton(WashingMachine wm) {
wm.setState(new StateOn())
}
}
Только учтите, что есть несколько способов реализовать это, креатив помогает!