Обзор темы [Шаблоны проектирования]

Затем: МотивацияНазначение

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

Затем: СтруктураМотивация

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

Рассмотрим, например, графический редактор, который позволяет пользователям рисовать и контролировать графические элементы (строки, многоугольники, текст, и т.д.). Ключевой абстракцией редактора является графический объект, который имеет доступную для редактирования форму и может себя рисовать. Интерфейс для графических объектов определяется абстрактным классом Shape. Редактор определяет подкласс Shape для каждого вида графического объекта: класс LineShape для строк, класс PolygonShape для многоугольников, и т.д.

Классы для элементарных геометрических форм подобно LineShape и PolygonShape довольно просты в реализации, потому что возможности их рисования и редактирования ограничены. Но подкласс TextShape, который может отображать и редактировать текст, значительно более трудный, так как даже простое редактирование текста включает сложную экранную модификацию и организацию буферизации данных. Между тем имеющийся в наличии комплект инструментальных средств интерфейса пользователя мог бы уже обеспечивать сложный класс TextView для отображения и редактирования текста. В идеале, мы хотели бы многократно использовать TextView, чтобы реализовать TextShape, но при разработке комплекта инструментальных средств не учитывался Shape. Так что мы не можем использовать объекты TextView и Shape как взаимозаменяемые.

Определим TextShape так, чтобы он адаптировал интерфейс TextView к Shape. Мы можем cделать это двумя способами: (1) - наследуя интерфейс Shape и реализацию TextView или (2) - помещая экземпляр TextView внутри TextShape и выполняя TextShape в терминах интерфейса TextView. Эти два подхода соответствуют классовой и объектной версиям шаблона Адаптера. Назовем TextShape адаптером.

 

Эта диаграмма иллюстрирует объектный случай адаптера. Видно как запросы BoundingBox, объявленные в классе Shape, преобразованы в запросы GetExtent, определенные в TextView. TextShape приспосабливает TextView к интерфейсу Shape, так что редактор может многократно использовать класс TextView.

Часто адаптер ответствен за функциональные возможности, которые адаптируемый класс не обеспечивает. Диаграмма показывает, как адаптер может выполнять такие обязательства. Пользователь должен иметь возможность "перемещать" каждый объект Shape в интерактивном режиме, но TextView не был разработан с учетом перемещения. TextShape может добавлять эти функциональные возможности, выполняя операцию Shape's CreateManipulator, которая возвращает экземпляр соответствующего подкласса Manipulator.

Manipilator - абстрактный класс для объектов, которые знают, как оживить Shape в ответ на ввод пользователя, чтобы это было подобно перемещению Shape. Подклассы манипулятора описываются для различных фигур; TextManipulator, например, является соответствующим подклассом для TextShape. Возвращая экземпляр TextManipulator, TextShape добавляет функциональные возможности, которых в TextView нет, но Shape требует.

Затем: Составные частиСтруктура

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

Объектный адаптер реализуется на основе объектной композиции:

Затем: СотрудничествоСоставные части