Javenue logo

Javenue

Программирование на Java

Информационные технологии

Паттерн Adapter на Java - Адаптер

Вернемся к рассмотрению структурных паттернов проектирования. На этот раз мы рассмотрим шаблон проектирования под названием Adapter (его еще называют Wrapper на ряду с паттерном Facade).

В этой статье поговорим о следующем:

Итак, паттерн Adapter используется для того, чтобы объекты с одним интерфейсом (контрактом) мог работать там, где необходим объект с совершенно другим интерфейсом. Существует два типа адаптеров - Class Adapter и Object Adapter.

Для начала мы рассмотрим каждый из этих типов, а потом я объясню разницу между двумя wrapper'ами - адаптером и фасадом.


Object Adapter

Object Adapter достигает своей цели с помощью композиции. На диаграмме, представленной ниже, клиенту требуется использовать интерфейс TargetInterface. Для этого создается класс ObjectAdapter, который реализует интерфейс TargetInterface, а также хранит объект класса Adaptee. При вызове метода targetMethod у Адаптера, осуществляется вызов соответствующего метода у адаптируемого интерфейса.

Диаграмма классов - Object Adapter

В самом простом случае реализация ObjectAdapter будет такой:

public class ObjectAdapter implements TargetInterface {
    private Adaptee adaptee;

    public void targetMethod() {
        adaptee.method()
    }
}

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


Class Adapter

В случае с Class Adapter'ом, для достижения нашей цели используется множественное наследование. Наш ClassAdapter наследуется от клиентского интерфейса и от Адаптируемого интерфейса. Так как в Java нет множественного наследования, то только один из предков может быть абстрактным/конкретным классом. Второй предок будет интерфейсом, что не всегда удобно.

Диаграмма классов:

Диаграмма классов - Class Adapter

А вот и тривиальная реализация класса ClassAdapter:

public class ClassAdapter extends Adaptee 
        implements TargetInterface {
    public void targetMethod() {
        method();
    }
}

Хочу обратить ваше внимание, что при такой реализации адаптера может возникнуть конфликт сигратур методов. Такой проблемы у Object Adapter нет.

Class Adapter считается более простым решением в случае когда не требуется жесткого разделения клиентского и адаптируемого интерфейсов.


Разница между Адаптером и Фасадом

Теперь хочу сказать несколько слов по поводу паттерна Фасад, который как и Адаптер является Wrapper'ом. Facade определяет новый интерфейс, в то время как Адаптер использует существующие интерфейсы.

Не стоит сравнивать Фасад и Адаптер так: мол, Фасад может оборачивать несколько классов, а Адаптер адаптирует только один. Очень может быть, что Адаптер понадобится для адаптации нескольких классов и наоборот, Фасад придется использовать для упрощения всего лишь одного комплексного класса. Так что разница этих двух паттернов не в количестве оборачиваемых сущностей, а в том, для чего они это делают.


Пример использования Адаптера в JDK

В стандартной библиотеке тоже можно встретить примеры использования Адаптера. Наверное, самый популярный вариант использования - это java.io.InputStreamReader и OutputStreamWriter.

Конструктор InputStreamReader принимает на вход InputStream и в результате адаптирует поток в Reader.

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



Комментариев: 4

  Выйти

  * для публикации комментариев нужно  

Иванов Иван:

10 лет прошло почти, так и не выложил =)

Nikolay Gusev:

11 лет прошло почти, так и не выложил =)

Sergiu:

12 лет прошло почти, так и не выложил =)

Begimay Bekturganova:

18 лет прошло почти, так и не выложил =)