Гипотетический случай из жизни:
Представьте, что вы сантехник и пришли поставить новый кран клиенту. Клиент вас встречает, чаем угощает, рассказывает "так мол и так, кран потек :-'( Надо новый ставить, стрый совсем плохой стал." Дает в руки вам смеситель, который вчера купил и провожает в ванную. Вы достаете разводной ключ и лихо откручиваете старый смеситель и уже собираетесь привернуть новый, как замечаете, что у наих трубки подвода воды разных диаметров. И тут вы могли бы сказать клиенту, что он не то купил и уйти, но чай выпит, в карманах пусто, а заработать хочется. Что делать?! Хорошо с собой есть такая классная штучка как муфта! С одной стороны она отлично наварачивается на трубки которые подводят воду, с другой замечательно вкручивается в новый смеситель, да и сама размером длинной пару сантиметров не более. Работа сделана, деньги в кармане, клиент доволен, проблема побеждена. Молодцы? А то!
Случай из практики разработки программ:
А теперь вернемся обратно к программированию, а именно к шаблонам проектирования. Скажите, у вас случалась ситуация, когда несколько человек проектирую одну систему, предварительно разделив ее на компоненты, а когда настает время соединить все вместе, то оно не соединяется. Ну не стыкуется один код с другим и все! Методы делают то, что нужно, а интерфейсы разные. Количество параметров не совпадает или нельзя просто вызвать метод, нужно еще предварительно настроить объект, который содержит метод. Проблема... :-( И что теперь делать? Деньги на разработку компонентов потрачены, менять интерфейсы стыковых классов нельзя(это, вроде как, основное ограничение), потому что они завязаны еще много где и придется перелопачиваться и там. А изменения там потребуют изменений еще где нибудь... Затратно это и рисковано!
Или так. Представьте, что нашли нужную библиотеку компонентов, а интегрировать со своим кодом не можете, интерфейсы разные. Изменить интерфейсы библиотеки тоже не можете, исходников нет и вообще по лицензии запрещено, что либо менять)
Основная проблема в том, что нужно использовать компоненты интерфейс которых не совпадает с интерфейсом, которого вы ожидаете в использовании.
Ситуация напоминает ситуацию со смесителем, да? Тут решение такое же, нам нужен специальный переходник - Адаптер. Этот Адаптер приведет интерфейс используемого класса к интерфейсу, который ожидает класс использующий его(клиент). Проблема будет решена, интеграция компонентов пройдет успешно и довольные разработчики наконец пойдут отмечать успех!
Плюсы:
- инкапсуляция реализации внешних классов (компонентов, библиотек), система становится независимой от интерфейса внешних классов;
- переход на использование других внешних классов не требует переделки самой системы, достаточно реализовать один класс Adapter.
Шаблон Адаптер позволяет в процессе проектирования не принимать во внимание возможные различия в интерфейсах уже существующих классов. Если есть класс, обладающий требуемыми методами и свойствами (по крайней мере, концептуально), то при необходимости всегда можно воспользоваться шаблоном Адаптер для приведения его интерфейса к нужному виду.все что выделено. Взято из Wiki
В отличии от шаблона Адаптер, шаблон Декоратор несет функции подключения дополнительных обязательств к объекту. И приведение одного интерфейса к другому это всего лишь побочный эффект.
Разница между Фасадом и Адаптером в том, что шаблон Фасад предназначен для упрощения интерфейса, тогда как шаблон Адаптер предназначен для приведения различных существующих интерфейсов к единому требуемому виду.
В диаграмме классов это будет выглядеть так.

Картинка взята с вики, а туда ее засунули, наверняка, из книжки GOF. Design Patterns
Клиент ожидал, что класс который он будет использовать имеет интерфейс класса Target, а вышло так, что ему доступен только интерфейс Adaptree. Функционально методы ожидаемый и тот, что есть делают все правильно. Входные данные и выходные соответствуют, проблема в том как данные передаются и как выводятся. Эти проблемы решает класс Adapter. Он является наследником класса Target, который предоставляет тот интерфейс, что нужен клиенту. И как наследник он переопределяет методы нужные клиенту, в которых обращается к классу Adaptree, который предоставляет текущую реализацию. Таким образом, класс Adapter полностью скрывает конвертацию передачи данных от одного класса к другому от класса клиента.
В будущем, если вернусь к этому шаблону, напишу про:
- Разницу между адаптером объектов и адаптером классов.
- Три подхода реализации Адаптера с примерами кода
913bd391-2bba-477c-8155-5b564936877e|2|4.0
Architecture, Design Patterns
architect, design patterns, adapter