Название и классификация образца
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Состояние - паттерн поведения объектов.

Назначение

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

State : мотивация

Рассмотрим класс TCPConnection, с помощью которого представлено сетевое соединение. Объект этого класса может находиться в одном из нескольких состояний: Established (установлено), Listening (прослушивание), Closed (закрыто). Когда объект TCPConnection получает запросы от других объектов, то в зависимости от текущего состояния он отвечает по-разному. Например, ответ на запрос Open (открыть) зависит от того, находится ли соединение в состоянии Closed или Established. Паттерн состояние описывает, каким образом объект TCPConnect ion может вести себя по-разному, находясь в различных состояниях.

Основная идея этого паттерна заключается в том, чтобы ввести абстрактный класс TCPState для представления различных состояний соединения. Этот класс объявляет интерфейс, общий для всех классов, описывающих различные рабочие состояния. В подклассах TCPState реализовано поведение, специфичное для конкретного состояния. Например, в классах TCPEstabli shed и TCPClosed реализовано поведение, характерное для состояний Established и Closed соответственно.

Рисунок 43

Класс TCPConnect ion хранит у себя объект состояния (экземпляр некоторого подкласса TCPState), представляющий текущее состояние соединения, и делегирует все зависящие от состояния запросы этому объекту. TCPConnection использует свой экземпляр подкласса TCPState для выполнения операций, свойственных только данному состоянию соединения.

При каждом изменении состояния соединения TCPConnection изменяет свой объект-состояние. Например, когда установленное соединение закрывается, TCPConnection заменяет экземпляр класса TCPEstablished экземпляром TCPCIosed.

State : применимость

Используйте паттерн состояние в следующих случаях:

• Когда поведение объекта зависит от его состояния и должно изменяться во время выполнения.

• Когда в коде операций встречаются состоящие из многих ветвей условные операторы, в которых выбор ветви зависит от состояния. Обычно в таком случае состояние представлено перечисляемыми константами. Часто одна и та же структура условного оператора повторяется в нескольких операциях. Паттерн состояние предлагает поместить каждую ветвь в отдельный класс. Это позволяет трактовать состояние объекта как самостоятельный объект, который может изменяться независимо от других.

State : структура

Рисунок 44

Участники

Context (TCPConnection) – контекст - определяет интерфейс, представляющий интерес для клиентов и - хранит экземпляр подкласса ConcreteState, которым определяется текущее состояние;

State (TCPState) – состояние - определяет интерфейс для инкапсуляции поведения, ассоциированного с конкретным состоянием контекста Context;

Подклассы ConcreteState ( TCPEstablished , TCPListen , TCPClosed ) - конкретное состояние - каждый подкласс реализует поведение, ассоциированное с некоторым состоянием контекста Context.

Отношения

Класс Context делегирует зависящие от состояния запросы текущему объекту ConcreteState. Контекст может передать себя в качестве аргумента объекту State, который будет обрабатывать запрос. Это дает возможность объекту-состоянию при необходимости получить доступ к контексту. Context - это основной интерфейс для клиентов. Клиенты могут конфигурировать контекст объектами состояния State. Один раз сконфигурировав контекст, Клиенты уже не должны напрямую связываться с объектами состояния. Либо Context, либо подклассы ConcreteState могут решить, при каких условиях и в каком порядке происходит смена состояний.

State : реализация

Что определяет переходы между состояниями. Паттерн состояние ничего не сообщает о том, какой участник определяет критерий перехода между состояниями. Если критерии зафиксированы, то их можно реализовать непосредственно в классе Context. Однако в общем случае более гибкий и правильный подход заключается в том, чтобы позволить самим подклассам класса State определять следующее состояние и момент перехода. Для этого в класс Context надо добавить интерфейс, позволяющий объектам State установить состояние контекста. Такую децентрализованную логику переходов проще модифицировать и расширять - нужно лишь определить новые подклассы State. Недостаток децентрализации в том, что каждый подкласс State должен «знать» еще хотя бы об одном подклассе, что вносит реализационные зависимости между подклассами.

Табличная альтернатива. Том Каргилл в книге C++Programming Style описывает другой способ структурирования кода, управляемого сменой состояний. Он использует таблицу для отображения входных данных на переходы между состояниями. С ее помощью можно определить, в какое состояние нужно перейти при поступлении некоторых входных данных. По существу, тем самым мы заменяем условный код поиском в таблице. Основное преимущество таблиц - в их регулярности: для изменения критериев перехода достаточно модифицировать только данные, а не код. Но есть и недостатки:
- поиск в таблице часто менее эффективен, чем вызов функции (виртуальной);
- представление логики переходов в однородном табличном формате делает критерии менее явными и, стало быть, более сложными для понимания;
- обычно трудно добавить действия, которыми сопровождаются переходы между состояниями. Табличный метод учитывает состояния и переходы между ними, но его необходимо дополнить, чтобы при каждом изменении состоянии можно было выполнять произвольные вычисления.
Главное различие между конечными автоматами на базе таблиц и паттерном состояние можно сформулировать так: паттерн состояние моделирует поведение, зависящее от состояния, а табличный метод акцентирует внимание на определении переходов между состояниями.

Создание и уничтожение объектов состояния. В процессе разработки обычно приходится выбирать между:
- созданием объектов состояния, когда в них возникает необходимость, и уничтожением сразу после использования;
- созданием их заранее и навсегда.
Первый вариант предпочтителен, когда заранее неизвестно, в какие состояния будет попадать система, и контекст изменяет состояние сравнительно редко. При этом мы не создаем объектов, которые никогда не будут использованы, что существенно, если в объектах состояния хранится много информации. Когда изменения состояния происходят часто, поэтому не хотелось бы уничтожать представляющие их объекты (ибо они могут очень скоро понадобиться вновь), следует воспользоваться вторым подходом. Время на создание объектов затрачивается только один раз, в самом начале, а на уничтожение - не затрачивается вовсе. Правда, этот подход может оказаться неудобным, так как в контексте должны хранитьсяссылки на все состояния, в которые система теоретически может попасть.








Паттерн Strategy.

Дата: 2019-02-25, просмотров: 226.