Назначение
Adapter обеспечивает взаимодействие двух классов путем преобразования интерфейса одного из них таким образом, чтобы им мог пользоваться другой класс.
- Нужно использовать класс, который вызывает метод интерфейса, причем необходимо использовать его с классом, который не реализует этот интерфейс;
- Возможно требуется преобразование аргументов или динамический выбор определенного метода во время выполнения.
Описание
Пусть есть полезный класс, который выполняя интересуемую работу взаимодействует с объектами других классов через определенный интерфейс. И есть другой класс, с объектами которого необходимо наладить взаимодействие. Проблема в том, что этот класс не реализует требуемого интерфейса и его нельзя изменить. В этом случае применяется шаблон адаптер — создается класс, реализующий требуемый интерфейс и делегирующий вызова его методов объекту адаптируемого класса.
Реализация
Реализация шаблона проста, за исключением одного момента: откуда класс адаптер получает экземпляры адаптируемого класса? Есть два подхода:
- Передать ссылку через параметр конструктора или метода.
- Сделать класс-адаптер внутренним классом Adaptee (если есть возможность изменить его). В этом случае связь Adapter — Adaptee устанавливается автоматически, т.к. внутренний класс принадлежит объекту внешнего класса.
Примеры
java.util.Arrays#asList()
java.io.InputStreamReader
Чем отличается
Decorator Adapter предназначен для изменения интерфейса объекта с сохранением функциональности. Декоратор, наоборот, оставляет интерфейс объекта неизменным, но при этом меняет (добавляет) функциональность.
Proxy Интерфейс, предоставляемый шаблоном Adapter, отличается от интерфейса объекта, а в случае с Proxy – совпадает. То есть объект Proxy имеет тот же интерфейс, заменителем которого он является.
Bridge У шаблона Bridge другое предназначение: он разделяет абстракцию компонента от его реализации, что позволяет изменять абстракцию или реализацию независимо друг от друга. Adapter нужен для использования готового объекта, который просто не подходит по интерфейсу. Bridge можно воспринимать как обобщение Strategy.
Facade Фасад через предоставление простого интерфейса позволяет изолировать клиента от сложных взаимосвязей между множеством объектов, в то время как Adapter приспосабливает один объект для использования через интерфейс, который он не реализует.
Iterator является примером Adapter. Он адаптирует коллекцию к интерфейсу последовательного перебора.
Варианты
- Можно использовать два интерфейса – требуемый целевой интерфейс (через который клиент взаимодействует с адаптером) и интерфейс адаптируемого объекта ( через который адаптер взаимодействует с адаптируемым объектом).
- Один “объединяющий” адаптер для нескольких адаптируемых объектов (этот случай ближе к паттерну Facade).
Ссылки
https://java-design-patterns.com/patterns/adapter/
https://github.com/iluwatar/java-design-patterns/tree/master/adapter
StackOverflow: How do the Proxy, Decorator, Adapter, and Bridge Patterns differ?
StackOverflow: Examples of GoF Design Patterns in Java’s core libraries
StackOverflow: Use for the adapter pattern in Java