Перейти к основному содержимому

Что это такое

Паттерн State («Состояние») даёт объекту разное поведение в разных состояниях за счёт того, что каждое состояние становится отдельным типом. Объект хранит своё текущее состояние и передаёт работу ему; переход в другое состояние — это просто замена значения.

Он заменяет разрастающийся switch status { ... }, повторённый в половине методов, одним маленьким типом на каждое состояние.


Пример: жизнь заказа

Заказ сначала новый, потом оплаченный, потом отправленный. Каждый тип состояния отвечает на Describe() по-своему и знает, какое состояние идёт следующим, — сам заказ вообще не содержит логики статусов.

Каждое состояние — это тип

Advance() навсегда останется в одну строку. Добавить состояние «доставлен» — это новый тип плюс один изменённый Next(): не нужно искать по коду ни одного switch.

Prompt
Напишите программу на Go с паттерном State: интерфейс State с методами Next и Describe, типы состояний New, Paid и Shipped (отправленный заказ так и остаётся отправленным) и структуру Order, которая хранит состояние и имеет метод Advance, заменяющий его. Проведите один заказ через все три состояния, печатая каждое описание.
Вывод: программа на Go и захваченный вывод

Когда его использовать

Используйте, когда поведение объекта действительно различается в зависимости от состояния и у состояний есть настоящие правила переходов: заказы, документы (черновик/на проверке/опубликован), соединения, персонажи в играх.

Не используйте, когда статус только показывается и никогда не меняет поведение. Если состояний меньше трёх и правила простые, поля-строки и одного switch вполне достаточно.


Плюсы и минусы

Плюсы: правила каждого состояния живут в одном маленьком типе; невозможные переходы просто не написаны; новые состояния добавляются, а не изменяют существующий код.

Минусы: много крошечных типов для простых автоматов; ход работы всего автомата разбросан по файлам — здесь помогает схема в комментарии.