Паттерн состояния является одним из паттернов поведенческого проектирования . Шаблон проектирования состояния используется, когда Объект меняет свое поведение в зависимости от его внутреннего состояния.
Если нам нужно изменить поведение объекта в зависимости от его состояния, мы можем иметь переменную состояния в объекте и использовать блок условия 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, я надеюсь, вам понравилось.