Статьи

Шаблон проектирования состояния в Java — пример учебника

Паттерн состояния является одним из паттернов поведенческого проектирования . Шаблон проектирования состояния используется, когда Объект меняет свое поведение в зависимости от его внутреннего состояния.

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

Ссылка: State Design Pattern на Java — пример учебного курса от нашего партнера по JCG Панкаджа Кумара в блоге Developer Recipes .