- •Предисловие 15
- •Предисловие
- •От авторов
- •Об авторах
- •Благодарности
- •Принятые в книге обозначения
- •Технические рекомендации
- •Дополнительные ресурсы
- •Глава 1. Введение
- •1.1. Понятие паттерна проектирования
- •Определение
- •Метафора
- •1.2. Формат описания паттернов проектирования
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода
- •Известные применения паттерна в .Net
- •1.3. Каталог паттернов проектирования
- •Порождающие
- •Структурные
- •Поведенческие
- •1.4. Техники ООП
- •Фабрика - Продукт
- •Фасад - Подсистема
- •Диспетчеризация
- •Цепочка объектов
- •Издатель-Подписчик
- •1.5. Принципы организации каталога
- •Цель паттерна
- •Уровень паттерна
- •1.6. Рекомендации по изучению паттернов
- •1.7. Рекомендации по применению паттернов
- •Глава 2. Порождающие паттерны
- •Игра - Лабиринт
- •Паттерн Abstract Factory
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода игры «Лабиринт»
- •Известные применения паттерна в .Net
- •Паттерн Builder
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода игры «Лабиринт»
- •Известные применения паттерна в .Net
- •Паттерн Factory Method
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода игры «Лабиринт»
- •Известные применения паттерна в .Net
- •Паттерн Prototype
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода игры «Лабиринт»
- •Известные применения паттерна в .Net
- •Паттерн Singleton
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода игры «Лабиринт»
- •Известные применения паттерна в .Net
- •Глава 3. Структурные паттерны
- •Паттерн Adapter
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Adapter уровня классов
- •Adapter уровня объектов
- •Структура паттерна на языке C#
- •Adapter уровня классов
- •Adapter уровня объектов
- •Участники
- •Отношения между участниками
- •Отношения между классами (для адаптера уровня классов)
- •Отношения между классами (для адаптера уровня объектов)
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Adapter уровня классов
- •Adapter уровня объектов
- •Особенности применения паттерна Adapter
- •Реализация
- •Пример кода
- •Известные применения паттерна в .Net
- •Паттерн Bridge
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода
- •Паттерн Composite
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Известные применения паттерна в .Net
- •Паттерн Decorator
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Известные применения паттерна в .Net
- •Паттерн Facade
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода
- •Паттерн Flyweight
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода
- •Известные применения паттерна в .Net
- •Паттерн Proxy
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода
- •Известные применения паттерна в .Net
- •Глава 4. Паттерны поведения
- •Паттерн Chain of Responsibility
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода
- •Паттерн Command
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода
- •Известные применения паттерна в .Net
- •Паттерн Interpreter
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Паттерн Iterator
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Классическое представление
- •Представление Microsoft .NET
- •Структура паттерна на языке C#
- •Классическое представление
- •Представление Microsoft .NET
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Известные применения паттерна в .Net
- •Паттерн Mediator
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода
- •Паттерн Memento
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Реализация
- •Паттерн Observer
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Модель вытягивания (Pull model)
- •Модель проталкивания (Push model)
- •Структура паттерна на языке C#
- •Модель вытягивания (Pull model)
- •Модель проталкивания (Push model)
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Реализация
- •Пример кода
- •Известные применения паттерна в .Net
- •Паттерн State
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Мотивация
- •Применимость паттерна
- •Результаты
- •Паттерн Strategy
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Применимость паттерна
- •Паттерн Template Method
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Применимость паттерна
- •Результаты
- •Реализация
- •Паттерн Visitor
- •Название
- •Также известен как
- •Классификация
- •Частота использования
- •Назначение
- •Введение
- •Структура паттерна на языке UML
- •Структура паттерна на языке C#
- •Участники
- •Отношения между участниками
- •Отношения между классами
- •Отношения между объектами
- •Применимость паттерна
- •Результаты
- •Реализация
- •Известные применения паттерна в .Net
- •Библиография
256
Мотивация
В качестве примера использования паттерна State предлагается построить машину состояний описывающую поведение отца, отправившего сына в школу. Условимся, что сын может получать только двойки или пятерки. Отец не хочет браться за ремень каждый раз, когда сын получает двойку и выбирает более тонкую тактику воспитания. Граф автомата, моделирующего умное поведение отца представлен ниже.
Граф 3.
Этот автомат имеет:
четыре состояния в которых может пребывать отец, S = { s0, s1, s2, s3 }, где:
s0 – Neutral (Нейтральное состояние)
s1 – Pity (Жалость)
s2 – Anger (Гнев)
s3 – Joy (Радость)
два входных сигнала – оценки полученные сыном в школе X = { x0, x1 }, где:
x0 = 2
x1 = 5
шесть выходных сигналов, т.е., действий отца Y = { y0, y1, y2, y3, y4, y5 }, где:
y0 - брать ремень;
y1 - ругать сына;
y2 - успокаивать сына;
y3 - надеяться;
y4 - радоваться;
y5 - ликовать;
Сына, получившего одну и туже оценку – ожидает дома совершенно различная реакция отца в зависимости от предыстории его учебы. Отец помнит, как его сын учился раньше и строит модель воспитания с учетом успехов и неудач сына. Например, после третьей двойки в истории (2, 2, 2) сына встретят ремнем (y0), а в истории (2, 2, 5, 2) – будут успокаивать(y2).
Каждая предыстория определяет текущее состояние автомата, при этом некоторые входные предыстории эквивалентны (те истории которые приводят автомат в одно и тоже состояние), например, история (2, 2, 5) эквивалентна пустой истории, которой соответствует начальное состояние.
257
Представим данный автомат таблично. Таблица 4 - определяет функцию переходов автомата из одного состояния в другое.
Функция переходов δ (sn, xn) определяется так: δ (s0, 2) = s1; δ (s2, 5) = s0; ….
δ |
2 |
5 |
|
|
|
s0 - Neutral |
s1 |
s3 |
|
|
|
s1 - Pity |
s2 |
s0 |
|
|
|
s2 - Anger |
s2 |
s0 |
|
|
|
s3 - Joy |
s1 |
s3 |
|
|
|
Таблица 4.
Таблица 5 - определяет функцию выходов λ (sn, xn) так: λ (s0, 2) = y2; λ (s2, 5) = y3; ….
λ |
2 |
5 |
|
|
|
s0 - Neutral |
y2 - успокаивать сына |
y4 - радоваться |
|
|
|
s1 - Pity |
y1 - ругать сына |
y3 - надеяться |
|
|
|
s2 - Anger |
y0 - брать ремень |
y3 - надеяться |
|
|
|
s3 - Joy |
y2 - успокаивать сына |
y5 - ликовать |
|
|
|
Таблица 5.
Для упрощения программной реализации примера, рекомендуется преобразовать исходный автомат Мили в эквивалентный по вычислительной мощности автомат Мура. Для этого требуется произвести расщепление тех состояний - sn, которым соответствует более одной функции выхода - λ (sn, xn).
|
x0 |
x1 |
Расщепление состояния S |
|
|
|
|
s0 - Neutral |
y3 |
y3 |
Не требуется |
|
|
|
|
s1 - Pity |
y2 |
y2 |
Не требуется |
|
|
|
|
s2 - Anger |
y0 |
y1 |
s2 = {s2, s4} |
|
|
|
|
s3 - Joy |
y4 |
y5 |
s3 = {s3, s5} |
|
|
|
|
Таблица 6.
Из таблицы преобразования видно, что произошло формирование двух новых состояний: {s4, s5}. Ранее в состоянии гнева – s2, отец либо ругал сына – y1, либо использовал ремень – y0, а в состоянии радости – s3, либо просто радовался – y4, либо ликовал – y5. Таким образом, функциональность можно распределить по состояниям согласно соответствия силы эмоциональной экспрессии состояния и выполняемого действия.
258
Например, s2-Гнев = {s2-Сильный Гнев, s4-Гнев}, s3-Радость = {s3-Радость, s5-Сильная Радость}. Соответственно: В
состоянии «простого» гнева - s4-Гнев, можно ругать сына - y1 - ругать сына, а в состоянии сильного гнева - s2-Сильный Гнев, можно использовать ремень - y0 - брать ремень. В состоянии «простой» радости - s3-Радость, можно радоваться - y4 - радоваться, а в состоянии сильной радости - s5-Сильная Радость, можно ликовать - y5 - ликовать. Представим новый автомат таблично.
Таблица 7 - определяет функцию переходов автомата из одного состояния в другое.
δ |
2 |
5 |
|
|
|
s0 - Neutral |
s1 |
s3 |
|
|
|
s1 - Pity |
s4 |
s0 |
|
|
|
s2 - Strong Anger |
s2 |
s0 |
|
|
|
s3 - Joy |
s1 |
s5 |
|
|
|
s4 - Anger |
s2 |
s0 |
|
|
|
s5 - Strong Joy |
s1 |
s5 |
|
|
|
Таблица 7. (Функции переходов - δ (sn, xn))
Таблица 8 - определяет функцию выходов.
λ |
2 |
|
5 |
|
|
|
|
s0 - Neutral |
y2 - успокаивать сына |
|
y4 - радоваться |
|
|
|
|
s1 - Pity |
y1 - ругать сына |
|
y3 - надеяться |
|
|
|
|
s2 - Strong Anger |
y0 - брать ремень |
|
y3 - надеяться |
|
|
|
|
s3 - Joy |
y2 - успокаивать сына |
|
y5 - ликовать |
|
|
|
|
s4 - Anger |
y0 - брать ремень |
|
y3 - надеяться |
|
|
|
|
s5 - Strong Joy |
y2 - успокаивать сына |
|
y5 - ликовать |
|
|
|
|
|
Таблица 8. (Функции выходов - λ (sn, xn)) |
|
259
Теперь представим автомат Мура в виде графа (в сравнении с автоматом Мили):
Автомат Мили |
Автомат Мура |
Граф 4.
Получившийся автомат Мура имеет:
шесть состояний в которых может пребывать отец, S = { s0, s1, s2, s3, s4, s5 }, где:
s0 – Neutral (Нейтральное состояние)
s1 – Pity (Жалость)
s2 – Strong Anger (Сильный Гнев)
s3 – Joy (Радость)
s4 – Anger (Гнев)
s5 – Strong Joy (Сильная Радость)
два входных сигнала – оценки полученные сыном в школе X = { x0, x1 }, где:
x0 = 2
x1 = 5
шесть выходных сигналов, т.е., действий отца Y = { y0, y1, y2, y3, y4, y5 }, где:
y0 - брать ремень;
y1 - ругать сына;
y2 - успокаивать сына;
y3 - надеяться;
y4 - радоваться;
y5 - ликовать;
Построив программу, реализующую логику данного конечного автомата и добавив активные устройства (звуковые динамики и механизм-манипулятор для управления пространственным положением ремня при обработке мягких тканей задней и латеральных поверхностей таза), можно воспитание своего сына поручить компьютеру.
260
Предлагается более подробно рассмотреть программную реализацию автомата Мура, имитирующего поведение умного отца.
Рассмотрим класс Father. Объект класса Father может находиться в одном из шести состояний:
NeutralState (Нейтральное состояние), PityState (Жалость), JoyState (Радость),
StrongJoyState (Сильная Радость), AngerState (Гнев), StrongAngerState (Сильный Гнев). Все классы состояний являются производными от базового абстрактного класса State. Объект типа Father хранит ссылку на определенный объект состояния.
public class Father
{
internal State State { get; set; }
public Father()
{
State = new NeutralState();
}
public void FindOut(Mark mark)
{
State.HandleMark(this, mark);
}
}
Объект класса Father делегирует все запросы (вызовы метода HandleMark()), объекту типа State, ссылка на который храниться в автосвойстве State.
Основная идея паттерна State заключается в том, чтобы ввести абстрактный класс State для представления различных состояний некоторого объекта, в данном примере для представления различных состояний объекта типа Father. Класс State предоставляет интерфейс для всех производных классов, реализующих различные состояния отца, т.е., объекта типа Father.
internal abstract class State
{
internal virtual void HandleMark(Father father, Mark mark)
{
ChangeState(father, mark);
}
protected abstract void ChangeState(Father father, Mark mark);
}
В подклассах класса State реализовано поведение, характерное для каждого конкретного состояния.
261
// Нейтральное состояние (S0) internal class NeutralState : State
{
internal NeutralState()
{
Console.WriteLine("Отец в нейтральном состоянии:"); Hope();
}
protected override void ChangeState(Father father, Mark mark)
{
switch (mark)
{
case Mark.Two:
{
father.State = new PityState(); // S1 break;
}
case Mark.Five:
{
father.State = new JoyState(); // S3 break;
}
}
}
private void Hope() // y3
{
Console.WriteLine("Надеется на хорошие оценки.");
}
}
// Состояние жалости (S1) internal class PityState : State
{
internal PityState()
{
Console.WriteLine("Отец в состоянии жалости:"); Calm();
}
protected override void ChangeState(Father father, Mark mark)
{
switch (mark)
{
case Mark.Two:
{
father.State = new AngerState(); // S4 break;
}
case Mark.Five:
{
father.State = new NeutralState(); // S0 break;
}
}
}
private void Calm() // y2
{
262
Console.WriteLine("Успокаивает сына.");
}
}
// Состояние сильного гнева (S2) internal class StrongAngerState : State
{
internal StrongAngerState()
{
Console.WriteLine("Отец в состоянии сильного гнева:"); BeatBelt();
}
protected override void ChangeState(Father father, Mark mark)
{
switch (mark)
{
case Mark.Two:
{
father.State = new StrongAngerState(); // S2 break;
}
case Mark.Five:
{
father.State = new NeutralState(); // S0 break;
}
}
}
private void BeatBelt() // y0
{
Console.WriteLine("Бьет сына ремнем.");
}
}
// Состояние радости (S3) internal class JoyState : State
{
internal JoyState()
{
Console.WriteLine("Отец в состоянии радости:"); Joy();
}
protected override void ChangeState(Father father, Mark mark)
{
switch (mark)
{
case Mark.Two:
{
father.State = new PityState(); // S1 break;
}
case Mark.Five:
{
father.State = new StrongJoyState(); // S5 break;
}
}
263
}
private void Joy() // y4
{
Console.WriteLine("Радуется успехам сына.");
}
}
// Состояние гнева (S4)
internal class AngerState : State
{
internal AngerState()
{
Console.WriteLine("Отец в состоянии гнева:"); Scold();
}
protected override void ChangeState(Father father, Mark mark)
{
switch (mark)
{
case Mark.Two:
{
father.State = new StrongAngerState(); // S2 break;
}
case Mark.Five:
{
father.State = new NeutralState(); // S0 break;
}
}
}
private void Scold() // y1
{
Console.WriteLine("Ругает сына.");
}
}
// Состояние сильной радости (S5) internal class StrongJoyState : State
{
internal StrongJoyState()
{
Console.WriteLine("Отец в состоянии сильной радости:"); Exult();
}
protected override void ChangeState(Father father, Mark mark)
{
switch (mark)
{
case Mark.Two:
{
father.State = new PityState(); // S1 break;