| Проблема |
Необходимо зафиксировать поведение объекта для реализации, например, механизма отката. |
| Решение |
Зафиксировать и вынести (не нарушая инкапсуляции) за пределы объекта его внутреннее состояние так, чтобы впоследствии можно было восстановить в нем объект. "Хранитель" сохраняет внутреннее состояние объекта "Хозяин" и запрещает доступ к себе всем другим объектам кроме "Хозяина", который имеет доступ ко всем данным для восстановления в прежнем состоянии. "Посыльный" может лишь передавать "Хранителя" другим объектам. "Хозяин" создает "Хранителя", содержащего снимок текущего внутреннего состояния и использует "Хранитель" для восстановления внутреннего состояния. "Посыльный" отвечает за сохранение "Хранителя", при этом не производит никаких операций над "Хранителем" и не исследует его внутреннее содержимое. "Посыльный" запрашивает "Хранитель" у "Хозяина", некоторое время держит его у себя, а затем возвращает "Хозяину".
|
| Преимущества |
Не раскрывается информация, которая доступна только "Хозяину", упрощается структура "Хозяина". |
| Недостатки |
С использованием "Хранителей" могут быть связаны значительные издержки, если "Хозяин" должен копировать большой объём информации, или если копирование должно проводиться часто. |
| Проблема |
Запрос должен быть обработан несколькими объектами. |
| Рекомендации |
Логично использовать данный паттерн, если имеется более одного объекта, способного обработать запрос и обработчик заранее неизвестен (и должен быть найден автоматически) или если весь набор обьектов, которые способны обработать запрос, должен задаваться автоматически. |
| Решение |
Связать объекты - получатели запроса в цепочку и передать запрос вдоль этой цепочки, пока он не будет обработан. "Обработчик" определяет интерфейс для обработки запросов, и, возможно, реализует связь с преемником, "КонкретныйОбработчик" обрабатывает запрос, за который отвечает, имеет доступ к своему преемнику ("КонкретныйОбработчик" направляет запрос к своему преемнику, если не может обработать запрос сам.
|
| Преимущества |
Ослабляется связанность (объект не обязан "знать", кто именно обработает его запрос). |
| Недостатки |
Нет гарантий, что запрос будет обработан, поскольку он не имеет явного получателя. |
| Проблема |
Необходимо обеспечить выполнение объектами разнородных функций. |
| Решение |
Обеспечить распределение обязанностей с высоким зацеплением. |
| Пример |
Если в примере для паттерна "Низкая связанность", см. 3.1.7 на класс "Регистрация" возлагать все новые и новые системные функции, связанные с системными операциями, то данный класс будет слишком перегружен и будет обладать низкой степенью зацепления. Второй рисунок для примера Low Coupling обладает более высоким уровнем зацепления и низким уровнем связывания (он является более предпочтительным). |
| Преимущества |
Классы с высокой степенью зацепления просты в поддержке и повторном использовании. |
| Недостатки |
Иногда бывает неоправданно использовать высокое зацепление для распределенных серверных обьектов. В этом случае для обеспечения быстродействия необходимо создать несколько более крупных серверных обьектов со слабым зацеплением. |
| Проблема |
"Кто" должен отвечать за обработку входных системных событий? |
| Решение |
Обязанности по обработке системных сообщений делегируются специальному классу. Контроллер - это объект, который отвечает за обработку системных событий и не относится к интерфейсу пользователя. Контроллер определяет методы для выполнения системных операций. |
| Рекомендации |
Для различных прецедентов логично использовать разные контроллеры (контроллеры прецедентов) - контроллеры не должны быть перегружены.
Внешний контроллер представляет всю систему целиком, его можно использовать, если он будет не слишком перегруженным (то есть, если существует лишь несколько системных событий). |
| Преимущества |
Удобно накапливать информацию о системных событиях (в случае, если системные операции выполняются в некоторой определенной последовательности).
Улучшаются условия для повторного использования компонентов (системные события обрабатываются Контроллером а не элементами интерфейса пользователя). |
| Недостатки |
Контроллер может оказаться перегружен. |
| Проблема |
Какой класс должен обеспечивать реализацию паттернов "Высокое зацепление" 3.2.13, и "Низкая связанность" 3.1.7? |
| Решение |
Присвоить группу обязанностей с высокой степенью зацепления классу, который не представляет конкретного понятия из предметной области (синтезировать искусственную сущность для обеспечения высокого зацепления и слабого связывания). |
| Пример |
См. пример паттерна "Информационный эксперт" 3.1.4. Какой класс должен сохранять экземпляры класса "Продажа" в реляционной базе данных? Если возложить эту обязанность на класс "Продажа", то будем иметь низкую степень зацепления и высокую степень связывания (поскольку класс "Продажа" должен быть связан с интерфейсом реляционной базы данных. Хранение обьектов в реляционной базе данных - это общая задача, которую придется решать для многих классов. Решением данной проблемы будет создание нового класса "ПостоянноеХранилище", ответственного за сохранение обьектов некоторого вида в базе данных.
|
| Преимущества |
Класс "ПостоянноеХранилище" будет обладать низкой степенью связывания и высокой степенью зацепления. |
| Недостатки |
Данным паттерном не следует злоупотреблять иначе все функции системы превратятся в объекты. |
| Проблема |
Создать семейство взаимосвязанных или взаимозависимых обьектов (не специфицируя их конкретных классов). |
| Решение |
Создать абстрактный класс, в котором объявлен интерфейс для создания конкретных классов. |
| Пример |
Какой класс должен отвечать за создание обьектов - адаптеров при использовании паттерна "Адаптер", см. 3.1.1. Если подобные объекты создаются неким объектом уровня предметной области, то будет нарушен принцип разделения обязанностей. |
| Преимущества |
Изолирует конкретные классы. Поскольку "Абстрактная фабрика" инкапсулирует ответственность за создание классов и сам процесс их создания, то она изолирует клиента от деталей реализации классов.
Упрощена замена "Абстрактной фабрики", поскольку она используется в приложении только один раз при инстанцировании. |
| Недостатки |
Интерфейс "Абстрактной фабрики" фиксирует набор обьектов, которые можно создать. Расширение "Абстрактной фабрики" для изготовления новых обьектов часто затруднительно. |
| Проблема |
"Кто" должен отвечать за создание экземпляров класса. |
| Решение |
Назначить классу В обязанность создавать объекты другого класса А |
| Рекомендации |
Логично использовать паттерн если класс В содержит, агрегирует, активно использует и т.п. объекты класса А. |
| Пример |
См. пример к паттерну "Информационный эксперт" в п. 3.1.4, необходимо определить, какой объект должен отвечать за создание экземпляра "ТоварПродажа". Логично, чтобы это был объект "Продажа", поскольку он содержит (агрегирует) несколько обьектов "ТоварПродажа".
|
| Преимущества |
Использование этого паттерна не повышает связанности, поскольку созданный класс, как правило, виден только для класса - создателя. |
| Недостатки |
Если процедура создания объекта достаточно сложная (например выполняется на основе некоего внешнего условия), логично использовать паттерн "Абстрактная Фабрика", см. 3.3.1, то есть, делегировать обязанность создания обьектов специальному классу. |
| Проблема |
Отделить конструирование сложного объекта от его представления, так чтобы в результате одного и того же конструирования могли получаться различные представления. Алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект и как они стыкуются между собой. |
| Решение |
"Клиент" создает объект - распорядитель "Директор" и конфигурирует его объектом - "Строителем". "Директор" уведомляет "Строителя" о том, что нужно построить очередную часть "Продукта". "Строитель" обрабатывает запросы "Директора" и добавляет новые части к "Продукту", затем "Клиент" забирает "Продукт" у "Строителя".
|
| Преимущества |
Объект "Строитель" предоставляет объекту "Директор" абстрактный интерфейс для конструирования "Продукта", за которым может скрыть представление и внутреннюю структуру продукта, и , кроме того, процесс сборки "продукта". Для изменения внутреннего представления "Продукта" достаточно определить новый вид "Строителя". Данный паттерн изолирует код, реализующий создание объекта и его представление. |
| Проблема |
Определить интерфейс для создания объекта, но оставить подклассам решение о том, какой класс инстанцировать, то есть, делегировать инстанцирование подклассам. |
| Решение |
Абстрактный класс "Создатель" объявляет ФабричныйМетод, возвращающий объект типа "Продукт" (абстрактный класс, определяющий интерфейс обьектов, создаваемых фабричным методом). "Создатель также может определить реализацию по умолчанию ФабричногоМетода, который возвращает "КонкретныйПродукт". "КонкретныйСоздатель" замещает ФабричныйМетод, возвращающий объект "КонкретныйПродукт". "Создатель" "полагается" на свои подклассы в определении ФабричногоМетода, возвращающего объект "КонкретныйПродукт".
|
| Преимущества |
Избавляет проектировщика от необходимости встраивать в код зависящие от приложения классы. |
| Недостатки |
Возникает дополнительный уровень подклассов. |