
Конечный автомат.
Основная идея в том, что программа может находиться в одном из нескольких состояний, которые всё время сменяют друг друга. Набор этих состояний, а также переходов между ними предопределён и конечен. Находясь в разных состояниях, программа может по-разному реагировать на одни и те же события, которые происходят с ней.
Такой подход может быть применён и к отдельным объектам. Например, объект Документ может принимать три состояния: Черновик, Модерация или Опубликован. В каждом из них его метод опубликовать будет работать по-разному:

Возможные состояния страницы и переходы между ними.
Машину состояний чаще всего реализуют с помощью множества условных операторов, if либо switch, которые проверяют текущее состояние объекта и выполняют соответствующее поведение. Наверняка вы уже реализовали хотя бы одну машину состояний в своей жизни, даже не зная об этом. Как на счёт вот такого кода, выглядит знакомо?
Основная проблема машины состояний построенной таким образом проявится, если в Документ добавить ещё десяток состояний. Каждый метод будет состоять из увесистого условного оператора, перебирающего доступные состояния.
Такой код крайне сложно поддерживать, так как любое изменение логики переходов влечёт за собой путешествие по всем методам и их условным операторам в поисках веток, которые изменились.
Путаница и нагромождение условий особенно сильно проявляется в старых проектах. Набор возможных состояний бывает трудно предопределить заранее, поэтому они всё время добавляются в процессе эволюции программы. Таким образом, то, что выглядело простым и эффективным в самом начале, может впоследствии стать проекцией большого макаронного монстра.
Паттерн Состояние предлагает создать отдельные классы для каждого состояния, в котором может пребывать контекстный объект, а затем вынести туда поведения, соответствующие этим состоянию.
Вместо того чтобы хранить код всех состояний, первоначальный объект (называемый «контекстом») будет содержать ссылку на один из объектов-состояний и делегировать ему работу, зависящую от состояния.

Страница делегирует выполнение своему активному состоянию.
Благодаря тому, что состояния будут иметь общий интерфейс, контекст сможет делегировать работу состоянию, не привязываясь к его классу. Состояние и поведение контекста можно будет изменить в любой момент, подключив к нему другой объект-состояние.
Очень важным нюансом, отличающим этот паттерн от , является то, что и контекст, и сами конкретные состояния могут знать друг о друге и инициировать переходы от одного состояния к другому.
Ваш смартфон ведёт себя по-разному, в зависимости от текущего состояния:
Контекст хранит ссылку на объект состояния и делегирует ему работу, зависящую от внутреннего состояния. Контекст работает с этим объектом через общий интерфейс состояний. Контекст должен иметь метод для присваивания ему ныового объекта-состояния.
Состояние описывает общий интерфейс для всех конкретных состояний.
Конкретные состояния реализуют поведения, связанные с определённым состоянием контекста. Иногда приходится создавать целые иерархии классов состояний, чтобы обобщить дублирующий код.
Состояние может иметь обратную ссылку на объект контекста. Через неё не только удобно получать из контекста нужную информацию, но и осуществлять смену его состояния.
И контекст, и объекты конкретных состояний могут решать, когда и какое следующее состояние будет выбрано. Чтобы переключить состояние, нужно подать другой объект-состояние в контекст.
В этом примере паттерн Состояние изменяет функциональность одних и тех же элементов управления музыкальным проигрывателем, в зависимости от того, в каком состоянии находится сейчас проигрыватель.

Пример изменение поведения проигрывателя с помощью состояний.
Объект проигрывателя содержит объект-состояние, которому и делегирует основную работу. Изменяя состояния, можно менять то, как ведут себя элементы управления проигрывателя.
Когда у вас есть объект, поведение которого кардинально меняется в зависимости от внутреннего состояния. Причём типов состояний много и их код часто меняется.
Паттерн предлагает выделить все поля и методы, связанные с определённым состоянием в собственные классы. Первоначальный объект будет постоянно ссылаться на один из объектов-состояний, делегируя ему большую часть работы. Для изменения состояния, в контекст достаточно будет подставляться другой объект-состояние.
Когда код класса содержит множество больших, похожих друг на друга, условных операторов, которые выбирают поведения в зависимости от текущих значений полей класса.
Паттерн предлагает переместить каждую ветку такого условного оператора в собственный класс. Тут же можно поселить и все поля, связанные с данным состоянием.
Когда вы сознательно используете табличную машину состояний, построенную на условных операторах, но вынуждены мириться с дублированием кода для похожих состояний и переходов.
Паттерн Состояние позволяет реализовать иерархическую машину состояний, базирующуюся на наследовании. Вы можете отнаследовать похожие состояния от одного родительского класса, и вынести туда весь дублирующий код.
Определитесь с классом, который будет играть роль контекста. Это может быть как существующий класс, в котором уже есть зависимость от состояния, так и новый класс, если код состояний размазан по нескольким классам.
Создайте интерфейс состояний. Он должен описывать методы, общие для всех состояний, обнаруженных в контексте. Заметьте, что не всё поведение контекста нужно переносить в состояние, а только то, которое зависит от состояний.
Для каждого фактического состояния, создайте класс, реализующий интерфейс состояния. Переместите весь код, связанный с конкретным состоянием в нужный класс. В конце концов, все методы интерфейса состояния должны быть реализованы.
При переносе поведения из контекста, вы можете столкнуться с тем, что это поведение зависит от приватных полей или методов контекста, к кторым нет доступа из состояния. Есть парочка способов обойти эту проблему. Самый простой — оставить поведение внутри контекста, вызывая его из объекта состояния. С другой стороны, вы может сделать классы состояний вложенными в класс контекста, и тогда они получат доступ ко всем приватным частям контекста. Но последний способ доступен только в некоторых языках программирования (например, Java, C#).
Создайте в контексте поле для хранения объектов-состояний, а также публичный метод для изменения значения этого поля.
Старые методы контекста, в которых находился зависимый от состояния код, замените на вызовы соответствующих методов объекта-состояния.
В зависимости от бизнес-логики, разместите код, который переключает состояние контекста либо внутри контекста, либо внутри классов конкретных состояний.
, и (а также слегка и ) имеют схожие структуры классов — все они построены на принципе «композиции», то есть делегирования работы другим объектам. Тем не менее, они отличаются тем, что решают разные проблемы. Помните, что паттерны — это не только рецепт построения кода определённым образом, но и описание проблем, которые привели к данному решению.
можно рассматривать как надстройку над . Оба паттерна используют композицию, чтобы менять поведение основного объекта, делегируя работу вложенным объектам-помощникам. Однако в Стратегии эти объекты не знают друг о друге и никак не связаны. В Состоянии сами конкретные состояния могут переключать контекст.