Адаптер - Паттерн (шаблон) проектирования

Название и классификация

Адаптер - паттерн, структурирующий классы и объекты (группа структурных паттернов)

Назначение

Преобразует интерфейс одного класса в интерфейс другого, который ожидают клиенты. Адаптер обеспечивает совместную работу классов с несовместимыми интерфейсами, которая без него была бы невозможна.

Псевдоним

Адаптер также известен под именем Wrapper (обертка)

Мотивация

Иногда класс из инструментальной библиотеки, спроектированный для повторного использования, не удается использовать только потому, что его интерфейс не соответствует тому, который нужен конкретному приложению.

адаптер мотивация

Применимость

Применяйте паттерн адаптер, когда:

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

Структура

Адаптер при работе с классами может использовать мноежственное наследование:

адаптер структура множественное наследование

а при работе с объектами - композицию:

адаптер структура композиция объектов

Участники

  1. Target (Shape) целевой: определяет зависящий от предметной области интерфейс, которым пользуется Client;
  2. Client (DrawingEditor) - клиент: вступает во взаимоотношения с объектами, удовлетворяющими интерфейсу Target;
  3. Adaptee (Textview) - адаптируемый: определяет существующий интерфейс, который нуждается в адаптации;
  4. Adapter (TextShape) - адаптер: адаптирует интерфейс Adaptee к интерфейсу Target.

Отношения

Клиенты вызывают операции экземпляра адаптера Adapter. В свою очередь адаптер вызывает операции адаптируемого объекта или класса Adaptee, который и выполняет запрос.

Результаты

Результаты применения адаптеров объектов и классов различны.

Адаптер класса:

  1. адаптирует Adaptee к Target, перепоручая действия конкретному классу Adaptee. Поэтому данный паттерн не будет работать, если мы захотим одновременно адаптировать класс и его подклассы;
  2. позволяет адаптеруAdapter заместить некоторые операции адаптируемого класса Adaptee, так как Adapter есть не что иное, как под класс Adaptee;
  3. вводит только один новый объект. Чтобы добраться до адаптируемого класса, не нужно никакого дополнительного обращения по указателю.

Адаптер объектов:

  1. позволяет одному адаптеру Adapter работать со многим адаптируемыми объектами Adaptee, то есть с самим Adaptee и его подклассами (если та ковые имеются). Адаптер может добавить новую функциональность сразу всем адаптируемым объектам;
  2. затрудняет замещение операций класса Adaptee. Для этого потребуется породить от Adaptee подкласс и заставить Adapter ссылаться на этот подкласс, а не на сам Adaptee.

Реализация

При изученни особенностей практической реализации паттерна Адаптер, следует обратить внимание на следующие вопросы:

  1. реализация адаптеров классов в C++
  2. сменные адаптеры

Заметим, что «узкий» интерфейс приводит к трем подходам к реализации:

  1. использование абстрактных операций.
  2. использование объектов-уполномоченных.
  3. параметризованные адаптеры.

Пример кода

Рассмотрим пример кода паттерна Адаптер на PHP

Известные применения

Пример, приведенный в разделе«Мотивация», заимствован из графического
приложения ET++Draw, основанного на каркасе ЕТ++[WGM88].

Сменные адаптеры широко применяются в системе ObjectWorks\Smalltalk [Раг90].

Родственные паттерны

Структура паттерна мост аналогична структуре адаптера, но у моста иное назначение. Он отделяет интерфейс от реализации, чтобы то и другое можно было изменять независимо. Адаптер же призван изменить интерфейс существующего объекта.

Паттерн декоратор расширяет функциональность объекта, изменяя его интерфейс. Таким образом, декоратор более прозрачен для приложения, чем адаптер.
Как следствие, декоратор поддерживает рекурсивную композицию, что для «чистых» адаптеров невозможно.
Заместитель определяет представителя или суррогат другого объекта, но не изменяет его интерфейс.