5.2.2.1.2. Паттерны проектирования поведения (Behavioral)
К поведенческим паттернам относятся [25]:
- Интерпретатор (Interpreter ) – GoF;
- Итератор (Iterator) или Курсор (Cursor) – GoF;
- Команда (Command), Действие (Action) или Транзакция (Транзакция) – GoF;
- Наблюдатель (Observer), Опубликовать – подписаться (Publish – Subscribe) или Delegation Event Model – GoF;
- Не разговаривайте с неизвестными (Don't talk to strangers) – GRASP;
- Посетитель (Visitor) – GoF;
- Посредник (Mediator) – GoF;
- Состояние (State) – GoF;
- Стратегия (Strategy) – GoF;
- Хранитель (Memento) – GoF;
- Цепочка обязанностей (Chain of Responsibility) – GoF;
- Шаблонный метод (Template Method) – GoF;
- Высокое зацепление (High Cohesion) – GRASP;
- Контроллер (Controller) – GRASP;
- Полиморфизм (Polymorphism) – GRASP;
- Искусственный (Pure Fabrication) – GRASP;
- Перенаправление (Indirection) – GRASP.
Приведем примеры 3-х их данных паттернов (табл. 5.2) [25].
Таблица
5.2.
Примеры поведенческих паттернов классов/объектов
Итератор (Iterator) или Курсор (Cursor) – GoF |
Проблема |
Составной объект, например, список, должен предоставлять доступ к своим элементам (объектам), не раскрывая их внутреннюю структуру, причем перебирать список требуется по-разному в зависимости от задачи. |
Решение |
Создается класс "Итератор", который определяет интерфейс для доступа и перебора элементов, "КонкретныйИтератор" реализует интерфейс класса "Итератор" и следит за текущей позицией при обходе "Агрегата". "Агрегат" определяет интерфейс для создания объекта – итератора. "КонкретныйАгрегат" реализует интерфейс создания итератора и возвращает экземпляр класса "КонкретныйИтератор", "КонкретныйИтератор" отслеживает текущий объект в агрегате и может вычислить следующий объект при переборе.
Данный паттерн поддерживает различные способы перебора агрегата, одновременно могут быть активны несколько переборов.
|
Посетитель (Visitor) – GoF |
Проблема |
Над каждым объектом некоторой структуры выполняется операция. Определить новую операцию, не изменяя классы объектов. |
Решение |
Клиент, использующий данный паттерн, должен создать объект класса "КонкретныйПосетитель", а затем посетить каждый элемент структуры. "Посетитель" объявляет операцию "Посетить" для каждого класса "КонкретныйЭлемент" (имя и сигнатура данной операции идентифицируют класс, элемент которого посещает "Посетитель" – то есть, посетитель может обращаться к элементу напрямую). "КонкретныйПосетитель" реализует все операции, объявленные в классе "Посетитель". Каждая операция реализует фрагмент алгоритма, определенного для класса соответствующего объекта в структуре.
Класс "КонкретныйПосетитель" предоставляет контекст для этого алгоритма и сохраняет его локальное состояние. "Элемент" определяет операцию "Принять", которая принимает "Посетителя" в качестве аргумента, "КонкретныйЭлемент" реализует операцию "Принять", которая принимает "Посетителя" в качестве аргумента. "СтруктураОбьекта" может перечислить свои аргументы и предоставить посетителю высокоуровневый интерфейс для посещения своих элементов.
Данный паттерн логично использовать, если в структуре присутствуют объекты многих классов с различными интерфейсами, и необходимо выполнить над ними операции, зависящие от конкретных классов, или если классы, устанавливающие структуру объектов, изменяются редко, но новые операции над этой структурой добавляются часто.
Данный паттерн упрощается добавление новых операций, объединяет родственные операции в классе "Посетитель".
В данном паттерне затруднено добавление новых классов "КонкретныйЭлемент", поскольку требуется объявление новой абстрактной операции в классе "Посетитель".
|
Состояние (State) – GoF |
Проблема |
Варьировать поведение объекта в зависимости от его внутреннего состояния |
Решение |
Класс "Контекст" делегирует зависящие от состояния запросы текущему объекту "КонкретноеСостояние" (хранит экземпляр подкласса "КонкретноеСостояние", которым определяется текущее состояние), и определяет интерфейс, представляющий интерес для клиентов. "КонкретноеСостояние" реализует поведение, ассоциированное с неким состоянием объекта "Контекст". "Состояние" определяет интерфейс для инкапсуляции поведения, ассоциированного с конкретным экземпляром "Контекста".
Данный паттерн локализует зависящее от состояния поведение и делит его на части, соответствующие состояниям, переходы между состояниями становятся явными.
|
5.2.2.1.3. Порождающие паттерны проектирования
К порождающим паттернам относятся [25]:
- Абстрактная фабрика (Abstract Factory, Factory) – GoF;
- Одиночка (Singleton) – GoF;
- Прототип (Prototype) – GoF;
- Создатель экземпляров класса (Creator) – GRASP;
- Строитель (Builder) – GoF;
- Фабричный метод (Factory Method) или Виртуальный конструктор (Virtual Constructor) – GoF.
Приведем примеры 2-х их данных паттернов (табл. 5.3) [25].
Таблица
5.3.
Примеры порождающих паттернов классов/объектов
Одиночка (Singleton) – GoF |
Проблема |
Какой специальный класс должен создавать "Абстрактную фабрику" и как получить к ней доступ? Необходим лишь один экземпляр специального класса, различные объекты должны обращаться к этому экземпляру через единственную точку доступа. |
Решение |
Создать класс и определить статический метод класса, возвращающий этот единственный объект.
Разумнее создавать именно статический экземпляр специального класса, а не объявить требуемые методы статическими, поскольку при использовании методов экземпляра можно применить механизм наследования и создавать подклассы. Статические методы в языках программирования не полиморфны и не допускают перекрытия в производных классах.
Решение на основе создания экземпляра является более гибким, поскольку впоследствии может потребоваться уже не единственный экземпляр объекта, а несколько.
|
Фабричный метод (Factory Method) или Виртуальный конструктор (Virtual Constructor) – GoF |
Проблема |
Определить интерфейс для создания объекта, но оставить подклассам решение о том, какой класс инстанцировать, то есть, делегировать инстанцирование подклассам. |
Решение |
Абстрактный класс "Создатель" объявляет Фабричный Метод, возвращающий объект типа "Продукт" (абстрактный класс, определяющий интерфейс объектов, создаваемых фабричным методом). "Создатель" также может определить реализацию по умолчанию Фабричного Метода, который возвращает "КонкретныйПродукт". "КонкретныйСоздатель" замещает Фабричный Метод, возвращающий объект "КонкретныйПродукт". "Создатель" "полагается" на свои подклассы в определении Фабричного Метода, возвращающего объект "КонкретныйПродукт".
Данный паттерн избавляет проектировщика от необходимости встраивать в код зависящие от приложения классы.
Однако при применении данного паттерна возникает дополнительный уровень подклассов.
|
5.2.2.2. Архитектурные системные паттерны
5.2.2.2.1. Структурные паттерны
К структурным паттернам относятся [25]:
- Репозиторий;
- Клиент/сервер;
- Обьектно – ориентированный, Модель предметной области (Domain Model), модуль таблицы (Data Mapper);
- Многоуровневая система (Layers) или абстрактная машина;
- Потоки данных (конвейер или фильтр).
Приведем пример одного их данных паттернов (табл. 5.4) [25].
Таблица
5.4.
Примеры стуктурных паттернов архитектуры
Многоуровневая система (Layers) или абстрактная машина |
Описание |
В соответствии с паттерном "Многоуровневая система" структурные элементы системы организуются в отдельные уровни с взаимосвязанными обязанностями таким образом, чтобы на нижнем уровне располагались низкоуровневые службы и службы общего назначения, а на более высоких – объекты уровня логики приложения. При этом взаимодействие и связывание уровней происходит сверху вниз. Связывания объектов снизу вверх следует избегать.
На рисунке показаны типичные уровни логической архитектуры системы.
Слой представления охватывает все, что имеет отношение к общению пользователя с системой. К главным функциям слоя представления относится отображение информации и интерпретация вводимых пользователем команд с преобразованием их в соответствующие операции в контексте домена (бизнес – логики) и источника данных.
Источник данных – подмножество функций, обеспечивающих взаимодействие со сторонними системами, которые выполняют
В отличие от архитектурного паттерна "Клиент – сервер", слои вовсе не обязательно должны располагаться на разных машинах.
Многоуровневая система может быть разработана пошагово (итеративно).
Недостатками данного паттерна являются:
- Изменение исходного кода влечет за собой переделку всех элементов системы, поскольку все элементы системы тесно связаны друг с другом.
- Логика приложения тесно связана с интерфейсом пользователя – затруднительно менять интерфейс или принципы реализации логики. Из-за высокой связанности, работу по реализации системы сложно разделить между разработчиками и, кроме того, сложно модифицировать функции приложения или переходить на новые технологии.
|