- •Предисловие 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
- •Библиография
109
Участники
Abstraction - Абстракция:
Предоставляет интерфейс для абстракции. Хранит ссылку на Implementor.
RefinedAbstraction - Уточненная абстракция:
Расширяет интерфейс, предоставляемый абстракцией.
Implementor - Реализатор:
Предоставляет интерфейс для реализации. Чаще всего класс Implementor предоставляет низкоуровневый интерфейс, а Abstraction предоставляет высокоуровневый интерфейс.
ConcreteImplementor - Конкретный реализатор:
Реализует интерфейс класса Implementor.
Отношения между участниками
Отношения между классами
Абстрактный класс Abstraction связан связью отношения агрегации с абстрактным классом
Implementor.
Конкретный класс RefinedAbstraction связан связью отношения наследования с абстрактным классом Abstraction.
Конкретные классы-реализаторы ConcreteImplementorA и ConcreteImplementorB связаны связью отношения наследования с абстрактным классом Implementor.
Отношения между объектами
Объекты типа Abstraction перенаправляют запросы клиента объектам типа Implementor.
Мотивация
Предлагается рассмотреть такую разновидность абстракции, как «переносимая абстракция», когда абстракция и ее реализация помещаются в раздельные (параллельные или частично параллельные) иерархии классов. Рассмотрим использование переносимой абстракции на простом примере построения приложения, способного использовать разные стили пользовательского интерфейса (например, стиль
Microsoft Windows и стиль Mac OS).
110
Создадим две иерархии, одну для интерфейсов окон (Window, MSWindow и MacWindow), а другую для реализаций элементов управления определенного стиля (WindowImp, MSWindowImp и MacWindowImp). Так, например, подкласс MSWindowImp предоставляет реализацию в стиле Microsoft Windows.
Все методы классов (MSWindow и MacWindow) производных от класса Window, используют методы из классов (MSWindowImp и MacWindowImp) производных от класса WindowImp. Такой подход отделяет абстракцию окна определенного стиля (например, MSWindow) от деталей реализации каждого отдельного элемента стиля (Form, Button и др.).
На диаграмме классов видно, что класс Window является вершиной иерархии абстракций, а класс WindowImp является вершиной иерархии реализаций (параллельной иерархии абстракций). Связь отношения агрегации между классами Window и WindowImp называется мостом. Мост между абстракцией
(Window, MSWindow и MacWindow) и реализацией (WindowImp, MSWindowImp и MacWindowImp). Это позволяет изменять абстракцию и реализацию независимо друг от друга.
См. Пример к главе: \007_Bridge\002_BridgeMotivation
Применимость паттерна
Паттерн Bridge рекомендуется использовать, когда:
Требуется избежать постоянной привязки абстракции к реализации. Иногда бывает необходимо выбирать нужную реализацию во время выполнения программы.
Требуется предоставить возможность расширения новыми подклассами и абстракции, и реализации.
Необходимо разделять одну реализацию между несколькими объектами и этот факт требуется скрыть от клиента. Примером этому может служить использование класса String и таблицы интернирования строк.
Необходимо избавиться от графов наследований, вложенных в графы наследования.
Параллельная иерархия всегда предпочтительней вложенного графа наследования.
Результаты
111
Паттерн Bridge обладает следующими преимуществами:
Отделение реализации от абстракции.
Реализация (Implementor) не имеет привязки к абстрактному интерфейсу абстракции (Abstraction), как это могло бы быть в случае использования вложенных графов наследования. Реализацию абстракции (RefinedAbstraction) можно конфигурировать во время выполнения программы, просто подставляя объекты нужных классов (ConcreteImplementorA или
ConcreteImplementorB). Разделение Abstraction и Implementor устраняет зависимости между абстракцией и реализацией во время компиляции, т.е., позволяет изменять абстракцию и реализацию независимо друг от друга.
Повышение степени расширяемости.
Имеется возможность независимо друг от друга расширять иерархии классов Abstraction и Implementor.
Сокрытие реализации от клиента.
От клиента можно скрыть наличие иерархии реализации (Implementor), предоставив только высокоуровневый интерфейс иерархии абстракции (Abstraction), за которым будет скрываться низкоуровневый интерфейс иерархии реализации (Implementor).
Реализация
Полезные приемы реализации паттерна Bridge:
Наличие только одного класса Implementor.
В том случае, если в программе имеется только одна реализация (ConcreteImplementor), то создавать абстрактный класс Implementor необязательно. Это частный случай использования паттерна Bridge, когда RefinedAbstraction ссылается на ConcreteImplementor. Тем не менее такое разделение полезно, так как позволит изменять ConcreteImplementor, при этом не перекомпилируя клиентскую часть кода.
Создание нужного объекта класса ConcreteImplementor.
Как принимается решение о том, экземпляр какого конкретного реализатора
(ConcreteImplementorA или ConcreteImplementorB) требуется создать? Если у класса RefinedAbstraction имеется информация о классах ConcreteImplementor, то класс
RefinedAbstraction в своем конструкторе может создать экземпляр нужного класса ConcreteImplementor. Например, если требуется создать коллекцию, поддерживающую несколько возможных реализаций, то решение о типе коллекции можно принять в зависимости от требуемого размера коллекции. Для хранения маленького числа элементов есть смысл создавать коллекцию типа ListDictionary, а для хранения большого числа элементов, коллекцию типа
Hashtable.
См. Пример к главе: \007_Bridge\003_BridgeCollections
112
Пример кода
Предлагается рассмотреть пример, из раздела «Мотивация», где рассматривается структура приложения, использующего различные стили пользовательского интерфейса (например, стиль Microsoft Windows и стиль Mac OS). Рассмотрим класс Window, который стоит на вершине иерархии абстракций и задает высокоуровневую базовую абстракцию для окна клиентских приложений:
abstract class Window
{
protected WindowImp implementor; protected Form form;
protected Button button;
// Operation
public virtual void Draw()
{
this.form.Controls.Add(button); Application.EnableVisualStyles(); Application.Run(this.form);
}
}
Класс Window содержит поле implementor типа WindowImp. Тип WindowImp представлен в виде абстрактного класса, в котором задан интерфейс взаимодействия с оконной системой. WindowImp является вершиной иерархии реализаций:
abstract class WindowImp
{
protected Button button; protected Form form;
public abstract Form DevDrawForm(); public abstract Button DevDrawButton();
}
Классы MSWindow и MacWindow, производные от класса Window являются представителями иерархии абстракций и определяют разнообразные варианты окон с различным внешним видом форм и кнопок:
class MacWindow : Window
{
public MacWindow()
{
this.implementor = new MacWindowImp(); this.form = this.implementor.DevDrawForm(); this.button = this.implementor.DevDrawButton();
}
// Operation
public override void Draw()
{
form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D; base.Draw();
}
}
113
class MSWindow : Window
{
public MSWindow()
{
this.implementor = new MSWindowImp(); this.form = this.implementor.DevDrawForm();
this.button = this.implementor.DevDrawButton();
}
// Operation
public override void Draw()
{
form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; base.Draw();
}
}
Конкретными представителями иерархии реализаций являются подклассы MacWindowImp и MSWindowImp класса WindowImp:
class MacWindowImp : WindowImp
{
public override Form DevDrawForm()
{
this.form = new Form(); this.form.AutoScaleDimensions = new SizeF(6F, 13F); this.form.AutoScaleMode = AutoScaleMode.Font; this.form.ClientSize = new Size(284, 172);
this.form.Name = "Mac Form"; this.form.Text = "Mac OS - Snow Leopard"; this.form.BackColor = Color.White;
return this.form;
}
public override Button DevDrawButton()
{
this.button = new Button(); this.button.Location = new Point(75, 70); this.button.Size = new Size(125, 25); this.button.Text = "Leopard"; this.button.ForeColor = Color.White; this.button.BackColor = Color.LightGray;
return this.button;
}
}
class MSWindowImp : WindowImp
{
public override Form DevDrawForm()
{
this.form = new Form(); this.form.AutoScaleDimensions = new SizeF(6F, 13F); this.form.AutoScaleMode = AutoScaleMode.Font; this.form.ClientSize = new Size(284, 172);
this.form.Name = "Microsoft Form"; this.form.Text = "Windows Explorer";
114
this.form.BackColor = Color.LightBlue;
return this.form;
}
public override Button DevDrawButton()
{
this.button = new Button(); this.button.Location = new Point(75, 70); this.button.Size = new Size(125, 25); this.button.Text = "Windows"; this.button.ForeColor = Color.Aqua; this.button.BackColor = Color.DarkBlue;
return this.button;
}
}