Паттерн состояния является одним из паттернов поведенческого проектирования . Шаблон проектирования состояния используется, когда Объект меняет свое поведение в зависимости от его внутреннего состояния.
Если нам нужно изменить поведение объекта в зависимости от его состояния, мы можем иметь переменную состояния в объекте и использовать блок условия if-else для выполнения различных действий в зависимости от состояния. Шаблон состояния используется для обеспечения систематического и потерянного способа достижения этого посредством реализаций контекста и состояния .
Context — это класс, который имеет ссылку на State для одной из конкретных реализаций State и перенаправляет запрос в объект состояния для обработки. Давайте разберемся с этим на простом примере.
Предположим, что мы хотим реализовать пульт дистанционного управления телевизором с помощью простой кнопки для выполнения действий. Если состояние включено, телевизор включится, а если состояние выключено, телевизор выключится.
Мы можем реализовать это, используя условие if-else, как показано ниже;
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package com.journaldev.design.state;public class TVRemoteBasic { private String state=""; public void setState(String state){ this.state=state; } public void doAction(){ if(state.equalsIgnoreCase("ON")){ System.out.println("TV is turned ON"); }else if(state.equalsIgnoreCase("OFF")){ System.out.println("TV is turned OFF"); } } public static void main(String args[]){ TVRemoteBasic remote = new TVRemoteBasic(); remote.setState("ON"); remote.doAction(); remote.setState("OFF"); remote.doAction(); }} |
Обратите внимание, что клиентский код должен знать конкретные значения, которые следует использовать для установки состояния удаленного управления. Более того, если число состояний увеличится, то тесная связь между реализацией и клиентским кодом будет очень трудно поддерживать и расширять.
Теперь мы будем использовать шаблон State для реализации вышеприведенного примера TV Remote.
Государственный интерфейс
Прежде всего мы создадим интерфейс State, который определит метод, который должен быть реализован различными конкретными состояниями и классом контекста.
|
1
2
3
4
5
6
|
package com.journaldev.design.state;public interface State { public void doAction();} |
Конкретные государственные реализации
В нашем примере у нас может быть два состояния — одно для включения телевизора и другое для его выключения. Таким образом, мы создадим две конкретные реализации состояний для этого поведения.
|
01
02
03
04
05
06
07
08
09
10
|
package com.journaldev.design.state;public class TVStartState implements State { @Override public void doAction() { System.out.println("TV is turned ON"); }} |
|
01
02
03
04
05
06
07
08
09
10
|
package com.journaldev.design.state;public class TVStopState implements State { @Override public void doAction() { System.out.println("TV is turned OFF"); }} |
Теперь мы готовы реализовать наш объект Context, который изменит свое поведение в зависимости от его внутреннего состояния.
Реализация контекста
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
package com.journaldev.design.state;public class TVContext implements State { private State tvState; public void setState(State state) { this.tvState=state; } public State getState() { return this.tvState; } @Override public void doAction() { this.tvState.doAction(); }} |
Обратите внимание, что Context также реализует State и сохраняет ссылку на его текущее состояние и перенаправляет запрос в реализацию состояния.
Тестовая программа
Теперь давайте напишем простую программу для тестирования нашей реализации TV Remote с использованием шаблона State.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
package com.journaldev.design.state;public class TVRemote { public static void main(String[] args) { TVContext context = new TVContext(); State tvStartState = new TVStartState(); State tvStopState = new TVStopState(); context.setState(tvStartState); context.doAction(); context.setState(tvStopState); context.doAction(); }} |
Вывод вышеуказанной программы такой же, как и в базовой реализации TV Remote, без использования какого-либо шаблона.
Преимущества использования шаблона State для реализации полиморфного поведения хорошо видны, вероятность ошибки меньше, и очень легко добавить больше состояний для дополнительного поведения, что делает его более устойчивым, легко поддерживаемым и гибким. Также шаблон State помог избежать условной логики if-else или switch-case в этом сценарии.
Шаблон состояния очень похож на шаблон стратегии, посмотрите шаблон стратегии в Java .
Вот и все для State Pattern в Java, я надеюсь, вам понравилось.