Состояние (State) — различия между версиями
Admin (обсуждение | вклад) (→Описание) |
Admin (обсуждение | вклад) (→Варианты) |
||
(не показано 11 промежуточных версий этого же участника) | |||
Строка 5: | Строка 5: | ||
=== Описание === | === Описание === | ||
+ | При каждом изменении состояния объект-Контекст меняет свой подобъект состояния ConcreteState. | ||
+ | Именно ConcreteState реализует обработку запроса. | ||
=== Использование === | === Использование === | ||
+ | Паттерн используется когда поведение объекта зависит от состояния, которое может меняться. | ||
+ | |||
+ | Если в коде операций встречаются состоящие из многих ветвей условные операторы, где выбор ветви зависит от состояния, , то использование паттерна Состояние позволяет избавиться от этой тяжеловесной конструкции, поместив каждую ветвь в отдельный класс. | ||
=== Реализация === | === Реализация === | ||
==== Диаграмма классов ==== | ==== Диаграмма классов ==== | ||
− | [[Изображение: | + | [[Изображение:StateCommon.png]] |
==== Участники==== | ==== Участники==== | ||
− | * | + | * '''Context''' - контекст |
+ | ** Определяет интерфейс, интересный для клиентов | ||
+ | ** Хранит экземпляр класса ConcreteState | ||
+ | * '''State''' - состояние | ||
+ | ** Определяет интерфейс поведения, связанного с конкретным состоянием (метод Handle()) | ||
+ | * '''ConcreteState''' - конкретное состояние | ||
+ | ** Реализует интерфейс Handle() | ||
+ | |||
+ | Класс Context хранит объект ConcreteState и делегирует ему зависящие от состояния запросы. | ||
+ | |||
+ | Контекст может передавать себя в качестве параметра методу Handle() объекта State, обрабатывающего запрос. | ||
+ | |||
+ | Либо Context либо ConcreteState могут решать, каким образом происходит смена состояний. | ||
+ | |||
+ | === Код === | ||
+ | <source lang="Csharp"> | ||
+ | abstract class State | ||
+ | { | ||
+ | public abstract void Handle(Context context); | ||
+ | } | ||
+ | |||
+ | class ConcreteStateA : State | ||
+ | { | ||
+ | public override void Handle(Context context) | ||
+ | { | ||
+ | context.State = new ConcreteStateB(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class ConcreteStateB : State | ||
+ | { | ||
+ | public override void Handle(Context context) | ||
+ | { | ||
+ | context.State = new ConcreteStateA(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class Context | ||
+ | { | ||
+ | public Context(State state) | ||
+ | { | ||
+ | this.State = state; | ||
+ | } | ||
− | + | public State State | |
− | + | { | |
+ | get; set; | ||
+ | } | ||
− | + | public void Request() | |
+ | { | ||
+ | State.Handle(this); | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
=== Достоинства и недостатки === | === Достоинства и недостатки === | ||
− | * | + | * Реализует зависящее от состояния поведение и делит его на части, соответствующие состояниям. Помещает поведение, связанное с конкретным состоянием, в отдельный объект. Добавление новых состояний достигается порождением новых подклассов класса state. |
+ | * Ликвидирует ветвление, которое возникает в обычной реализации. | ||
+ | * Делает явным переход между состояниями (при изменении переменной состояния) | ||
+ | * Действия в зависимости от состояния разбросаны по многим классам, и за этим может быть трудно следить. | ||
=== Варианты === | === Варианты === | ||
− | * | + | * Вместо того чтобы возлагать ответственность за переход в другое состояние на обработчик текущего состояния, можно использовать таблицу для отображения входных данных на переходы между состояниями (конечный автомат) |
+ | * Ненужные уже объекты состояния можно уничтожать |
Текущая версия на 10:30, 22 июля 2014
Назначение
Позволяет объекту менять своё поведение в зависимости от состояния. Состояние моделируется абстрактным объектом с множеством подобъектов (состояний).
Описание
При каждом изменении состояния объект-Контекст меняет свой подобъект состояния ConcreteState.
Именно ConcreteState реализует обработку запроса.
Использование
Паттерн используется когда поведение объекта зависит от состояния, которое может меняться.
Если в коде операций встречаются состоящие из многих ветвей условные операторы, где выбор ветви зависит от состояния, , то использование паттерна Состояние позволяет избавиться от этой тяжеловесной конструкции, поместив каждую ветвь в отдельный класс.
Реализация
Диаграмма классов
Участники
- Context - контекст
- Определяет интерфейс, интересный для клиентов
- Хранит экземпляр класса ConcreteState
- State - состояние
- Определяет интерфейс поведения, связанного с конкретным состоянием (метод Handle())
- ConcreteState - конкретное состояние
- Реализует интерфейс Handle()
Класс Context хранит объект ConcreteState и делегирует ему зависящие от состояния запросы.
Контекст может передавать себя в качестве параметра методу Handle() объекта State, обрабатывающего запрос.
Либо Context либо ConcreteState могут решать, каким образом происходит смена состояний.
Код
abstract class State
{
public abstract void Handle(Context context);
}
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateB();
}
}
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateA();
}
}
class Context
{
public Context(State state)
{
this.State = state;
}
public State State
{
get; set;
}
public void Request()
{
State.Handle(this);
}
}
Достоинства и недостатки
- Реализует зависящее от состояния поведение и делит его на части, соответствующие состояниям. Помещает поведение, связанное с конкретным состоянием, в отдельный объект. Добавление новых состояний достигается порождением новых подклассов класса state.
- Ликвидирует ветвление, которое возникает в обычной реализации.
- Делает явным переход между состояниями (при изменении переменной состояния)
- Действия в зависимости от состояния разбросаны по многим классам, и за этим может быть трудно следить.
Варианты
- Вместо того чтобы возлагать ответственность за переход в другое состояние на обработчик текущего состояния, можно использовать таблицу для отображения входных данных на переходы между состояниями (конечный автомат)
- Ненужные уже объекты состояния можно уничтожать