Шаблоны проектирования

Димитров Вячеслав Михайлович, старший преподаватель кафедры ИМО, dimitrov@cs.petrsu.ru

Шаблоны проектирования.

  1. Идея была заимствована из архитектуры (профессор Кристофер Александр).
  2. 23 шаблона из книги 1995 г. Design Patterns — Elements of Reusable Object-Oriented Software.

Для чего полезно иметь представления о шаблонах.

  1. Проверенные решения.
  2. Стандартизация кода.
  3. Общий язык.

Группы шаблонов.

  1. Порождающие шаблоны - определяют процесс порождения объектов.
  2. Структурные шаблоны - как классы и объекты объединяются в более крупные структкры.
  3. Поведенческие шаблоны - определяют алгоритмы и взаимодействия между классами и объектами.

Порождающие шаблоны.

  1. Абстрактная фабрика (Abstract Factory)
  2. Строитель (Builder)
  3. Фабричный метод (Factory Method)
  4. Прототип (Prototype)
  5. Одиночка (Singleton)

Абстрактная фабрика (Abstract Factory).

  1. Создание семейства объектов без их спецификации.
  2. Система не должна зависеть от способа создания.
  3. Создаваемые объекты должны использоваться вместе и являются взаимосвязанными.

Абстрактная фабрика.

Строитель (Builder)

  1. Процесс создания объекта не должен зависеть от процесса создания его частей.
  2. Builder определяет интерфейс конструирования продукта по частям.
  3. Director управляет процессом создания, не зная, какой продукт будет создан в результате.
  4. ConcreteBuilder — конкретный строитель, который создает только известный ему объект класса Product.

Строитель (Builder)

Фабричный метод (Factory Method)

  1. Когда заранее неизвестно, объекты каких типов необходимо создавать.
  2. Когда система должна быть независимой от процесса создания новых объектов и расширяемой: в нее можно легко вводить новые классы, объекты которых система должна создавать.
  3. Когда создание новых объектов необходимо делегировать из базового класса классам наследникам.

Фабричный метод (Factory Method)

Прототип (Prototype)

  1. Клонирование объектов.
  2. Когда желательно избежать наследования создателя объекта.
  3. Когда клонирование объекта является более предпочтительным вариантом нежели его создание и инициализация с помощью конструктора.
  4. Когда создание копии объекта проще и быстрее, чем порождение его стандартным путем, используя операцию new и включая инициализацию полей.

Прототип (Prototype)

Одиночка (Singleton)

  1. У класса есть только один экземпляр.
  2. Глобальную точку доступа к классу.
  3. Аналог глобальной переменной.

Одиночка (Singleton)

Структурные шаблоны.

  1. Адаптер (Adapter)
  2. Мост (Bridge)
  3. Компоновщик (Composite)
  4. Декоратор (Decorator)
  5. Фасад (Facade)
  6. Приспособленец (Flyweight)
  7. Заместитель (Proxy)

Адаптер (Adapter)

  1. Когда необходимо использовать имеющийся класс, но его интерфейс не соответствует потребностям бизнесс логики.
  2. Когда надо использовать уже существующий класс совместно с другими классами, интерфейсы которых не совместимы.
  3. Target: представляет объекты, которые используются клиентом
  4. Client: использует объекты Target для реализации своих задач
  5. Adaptee: представляет адаптируемый класс, который мы хотели бы использовать у клиента вместо объектов Target
  6. Adapter: собственно адаптер, который позволяет работать с объектами Adaptee как с объектами Target.

Адаптер (Adapter)

Мост (Bridge)

  1. Отделяет абстракцию от реализации таким образом, чтобы и абстракцию, и реализацию можно было изменять независимо друг от друга.
  2. Когда надо избежать постоянной привязки абстракции к реализации.
  3. Когда наряду с реализацией надо изменять и абстракцию независимо друг от друга. То есть изменения в абстракции не должно привести к изменениям в реализации.

Мост (Bridge)

Компоновщик (Composite)

  1. Когда объекты должны быть реализованы в виде иерархической древовидной структуры
  2. Когда клиенты единообразно должны управлять как целыми объектами, так и их составными частями. То есть целое и его части должны реализовать один и тот же интерфейс
  3. Component: определяет интерфейс для всех компонентов в древовидной структуре
  4. Composite: представляет компонент, который может содержать другие компоненты и реализует механизм для их добавления и удаления
  5. Leaf: представляет отдельный компонент, который не может содержать другие компоненты
  6. Client: клиент, который использует компоненты

Компоновщик (Composite)

Декоратор (Decorator)

  1. Когда надо динамически добавлять к объекту новые функциональные возможности.
  2. Когда применение наследования неприемлемо.

Декоратор (Decorator)

  1. Component: абстрактный класс, который определяет интерфейс для наследуемых объектов.
  2. ConcreteComponent: конкретная реализация компонента, в которую с помощью декоратора добавляется новая функциональность.
  3. Decorator: собственно декоратор, реализуется в виде абстрактного класса и имеет тот же базовый класс, что и декорируемые объекты. Поэтому базовый класс Component должен быть по возможности легким и определять только базовый интерфейс.

Декоратор (Decorator)

Фасад (Facade)

  1. Когда имеется сложная система, и необходимо упростить с ней работу. Фасад позволит определить одну точку взаимодействия между клиентом и системой.
  2. Когда надо уменьшить количество зависимостей между клиентом и сложной системой. Фасадные объекты позволяют отделить, изолировать компоненты системы от клиента и развивать и работать с ними независимо.
  3. Когда нужно определить подсистемы компонентов в сложной системе. Создание фасадов для компонентов каждой отдельной подсистемы позволит упростить взаимодействие между ними и повысить их независимость друг от друга.

Фасад (Facade)

  1. Знает, какие классы подсистемы отвечают за запрос.
  2. Делегирует запросы клиентов соответствующим объектам подсистем.
  3. Реализовывают функционал подсистемы
  4. Обрабатывают методы, назначенные объектом Facade.
  5. Не знают о фасаде и не ссылаются на него.

Фасад (Facade)

Приспособленец (Flyweight)

  1. Используется преимущественно для оптимизации работы с памятью.
  2. в приложении используется большое число очень схожих экземпляров заданного класса;
  3. (и) часть состояния объекта является контекстной и может быть легко вынесена во внешние структуры;
  4. (и) после вынесения части состояния, все экземпляры становятся одинаковыми и это дает возможность заменить их одним;
  5. (и) приложение не проверяет идентичность объектов, т.к. в этом случае все якобы самостоятельные экземпляры являются одним объектом.

Приспособленец (Flyweight)

Заместитель (Proxy)

  1. Удаленный заместитель — отвечает за кодирование запроса и его аргументов для работы с компонентом в другом адресном пространстве.
  2. Виртуальный заместитель — может кэшировать дополнительную информацию о реальном компоненте, чтобы отложить его создание.
  3. Защищающий заместитель — проверяет, имеет ли вызывающий объект необходимые для выполнения запроса прав.

Заместитель (Proxy)

Поведенческие шаблоны.

Определяют алгоритмы и взаимодействие между классами и объектами
  1. Цепочка обязанностей (Chain of responsibility)
  2. Команда (Command)
  3. Интерпретатор (Interpreter)
  4. Итератор (Iterator)
  5. Посредник (Mediator)

Поведенческие шаблоны.

  1. Хранитель (Memento)
  2. Наблюдатель (Observer)
  3. Состояние (State)
  4. Стратегия (Strategy)
  5. Шаблонный метод (Template method)
  6. Посетитель (Visitor)

Цепочка обязанностей (Chain of responsibility)

  1. Позволяет избежать привязки отправителя запроса к его получателю
  2. Когда имеется более одного объекта, который может обработать определенный запрос;
  3. Когда надо передать запрос на выполнение одному из нескольких объект, точно не определяя, какому именно объекту;
  4. Когда набор объектов задается динамически.

Цепочка обязанностей (Chain of responsibility)

Команда (Command)

  1. Когда необходимо обеспечить выполнение очереди запросов, а также их возможную отмену.
  2. Когда надо поддерживать логгирование изменений в результате запросов.
  3. Когда необходимо параметризировать объекты выполняемым действием, ставить запросы в очередь или поддерживать операции отмены (undo) и повтора (redo) действий.

Команда (Command)

Интерпретатор (Interpreter)

  1. Следует использовать когда вам необходимо интерпретировать запись в другом языке

Интерпретатор (Interpreter)

Итератор (Iterator)

  1. Представляет доступ ко всем элементам составного объекта, не раскрывая его внутреннего представления
  2. Когда необходимо осуществить обход объекта без раскрытия его внутренней структуры.
  3. Когда имеется набор составных объектов, и надо обеспечить единый интерфейс для их перебора.
  4. Когда необходимо предоставить несколько альтернативных вариантов перебора одного и того же объекта.

Итератор (Iterator)

Посредник (Mediator)

  1. Обеспечивает взаимодействие множества объектов без необходимости ссылаться друг на друга.
  2. Когда имеется множество взаимосвязаных объектов, связи между которыми сложны и запутаны.
  3. Когда необходимо повторно использовать объект, однако повторное использование затруднено в силу сильных связей с другими объектами.

Посредник (Mediator)

Хранитель (Memento)

  1. Позволяет выносить внутреннее состояние объекта за его пределы для последующего возможного восстановления объекта без нарушения принципа инкапсуляции.
  2. Когда нужно сохранить состояние объекта для возможного последующего восстановления.
  3. Когда сохранение состояния должно проходить без нарушения принципа инкапсуляции.

Хранитель (Memento)

Наблюдатель (Observer)

  1. определяет зависимость типа «один ко многим» между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом и автоматически обновляются.
  2. Когда система состоит из множества классов, объекты которых должны находиться в согласованных состояниях
  3. Когда общая схема взаимодействия объектов предполагает две стороны: одна рассылает сообщения и является главным, другая получает сообщения и реагирует на них. Отделение логики обеих сторон позволяет их рассматривать независимо и использовать отдельно друга от друга.
  4. Когда существует один объект, рассылающий сообщения, и множество подписчиков, которые получают сообщения. При этом точное число подписчиков заранее неизвестно и процессе работы программы может изменяться.

Наблюдатель (Observer)

Состояние (State)

  1. предполагает выделение базового класса или интерфейса для всех допустимых операций и наследника для каждого возможного состояния
  2. Когда поведение объекта должно зависеть от его состояния и может изменяться динамически во время выполнения
  3. Когда в коде методов объекта используются многочисленные условные конструкции, выбор которых зависит от текущего состояния объекта

Состояние (State)

Стратегия (Strategy)

  1. стратегия инкапсулирует определенное поведение с возможностью его подмены.
  2. Когда есть несколько схожих классов , которые отличаются поведением. Можно задать один основной класс, а разные варианты поведения вынести в отдельные классы и при необходимости их применять;
  3. Когда необходимо обеспечить выбор из нескольких вариантов решений, которые можно легко менять в зависимости от условий;
  4. Когда необходимо менять поведение классов и объектов на стадии выполнения программы;
  5. Когда класс, применяющий определенную функциональность, ничего не должен знать о ее реализации

Стратегия (Strategy)

Шаблонный метод (Template method)

  1. определяет основу алгоритма и позволяет подклассам переопределять некоторые шаги алгоритма, не изменяя его структуры в целом.
  2. Когда планируется, что в будущем подклассы должны будут переопределять различные этапы алгоритма без изменения его структуры
  3. Когда в классах, реализующим схожий алгоритм, происходит дублирование кода. Вынесение общего кода в шаблонный метод уменьшит его дублирование в подклассах.

Шаблонный метод (Template method)

Посетитель (Visitor)

  1. описывает операцию, выполняемую с каждым объектом из некоторой иерархии классов.
  2. Паттерн Посетитель определяет операцию, выполняемую на каждом элементе из некоторой структуры. Позволяет, не изменяя классы этих объектов, добавлять в них новые операции.
  3. Является классической техникой для восстановления потерянной информации о типе.
  4. Паттерн Посетитель позволяет выполнить нужные действия в зависимости от типов двух объектов.
  5. Предоставляет механизм двойной диспетчеризации.

Посетитель (Visitor)

Критика ООП.

  1. Изменчивое состояние.
  2. Не моделируют реальную предметную область.
  3. Функции и код вместе.
  4. Сложно тестировать (нужно создавать контекст).