Мой взгляд на предмет.
Все четыре шаблона имеют много общего, все четыре иногда неофициально называют обертками, или обертками. Все используют композицию, переносят тему и делегируют выполнение субъекту в какой-то момент, отображая один вызов метода на другой. Они избавляют клиента от необходимости создавать другой объект и копировать все соответствующие данные. При разумном использовании они экономят память и процессор.
Путем поощрения слабой связи они делают стабильный код менее подверженным неизбежным изменениям и лучше читаемым для коллег-разработчиков.
Адаптер
Адаптер адаптирует субъект (адаптай) к другому интерфейсу. Таким образом, мы можем добавить объект в коллекцию номинально разных типов.
Адаптер предоставляет клиенту только соответствующие методы, может ограничивать все остальные, раскрывая цели использования для определенных контекстов, таких как адаптация внешней библиотеки, делая ее менее общей и более сфокусированной на потребностях наших приложений. Адаптеры повышают удобочитаемость и самоописание нашего кода.
Адаптеры защищают одну команду от изменчивого кода других команд; инструмент спасения жизни при работе с оффшорными командами; -)
Менее упоминаемая цель - не допустить превышения аннотациями в предметном классе. С таким количеством фреймворков, основанных на аннотациях, использование становится более важным, чем когда-либо.
Адаптер помогает обойти ограничение Java только для одного наследования. Он может объединять несколько адаптеров в одном конверте, создавая впечатление множественного наследования.
Код мудрый, адаптер «тонкий». Он не должен добавлять много кода к классу adaptee, кроме простого вызова метода adaptee и случайных преобразований данных, необходимых для таких вызовов.
В JDK или базовых библиотеках не так много хороших примеров адаптеров. Разработчики приложений создают адаптеры, чтобы адаптировать библиотеки к интерфейсам приложений.
декоратор
Декоратор не только делегирует, не только отображает один метод на другой, он делает больше, они изменяют поведение некоторых подчиненных методов, он может решить вообще не вызывать подчиненный метод, делегировать другому объекту, вспомогательному объекту.
Декораторы обычно добавляют (прозрачно) функциональность к обернутому объекту, такую как регистрация, шифрование, форматирование или сжатие объекта. Эта новая функциональность может принести много нового кода. Следовательно, декораторы обычно намного «толще», чем адаптеры.
Декоратор должен быть подклассом интерфейса субъекта. Их можно использовать прозрачно вместо своих предметов. Посмотрите BufferedOutputStream, это все еще OutputStream и может использоваться как таковой. Это основное техническое отличие от адаптеров.
Примеры учебников для всего семейства декораторов легко доступны в JDK - Java IO. Все классы, такие как BufferedOutputStream , FilterOutputStream и ObjectOutputStream являются декораторами OutputStream . Они могут быть наслоены луком, где один декоратор украшен снова, добавляя больше функциональности.
Proxy
Прокси не типичная оболочка. Обернутый объект, субъект прокси, может еще не существовать во время создания прокси. Прокси часто создает его внутри. Это может быть тяжелый объект, созданный по требованию, или это удаленный объект в другой JVM или другом сетевом узле и даже не-Java-объект, компонент в собственном коде. Он вообще не должен оборачиваться или делегироваться другому объекту.
Наиболее типичными примерами являются удаленные прокси, инициализаторы тяжелых объектов и прокси доступа.
Удаленный прокси - субъект находится на удаленном сервере, другой JVM или даже не
Система Java. Прокси переводит вызовы методов в вызовы RMI / REST / SOAP или
все, что необходимо, защищая клиента от подверженности
технология.
Lazy Load Proxy - полностью инициализировать объект только при первом использовании или
первая интенсивностьIve использования.
Access Proxy - контроль доступа к теме.
Фасад
Фасад тесно связан с принципом проектирования наименьших знаний (Закон Деметры).
Фасад очень похож на адаптер. Они оба обертывают, они отображают один объект на другой, но различаются по назначению. Фасад сплющивает сложную структуру предмета, сложный объект графа, упрощая доступ к сложной структуре.
Фасад оборачивает сложную конструкцию, обеспечивая ей плоский интерфейс. Это препятствует тому, чтобы объект клиента подвергался внутренним отношениям в предметной структуре, следовательно, способствует слабой связи.
мост
Более сложный вариант шаблона адаптера, где меняется не только реализация, но и абстракция. Это добавляет еще одну косвенность к делегации. Дополнительная делегация - это мост. Он отделяет адаптер даже от адаптационного интерфейса. Он увеличивает сложность больше, чем любой другой шаблон упаковки, поэтому применяйте его осторожно.
Различия в конструкторах
Различия в шаблонах также очевидны при взгляде на их конструкторы.
Прокси не переносит существующий объект. В конструкторе нет темы.
Декоратор и Адаптер выполняет обертывание уже существующего объекта, и обычно это
предоставляется в конструкторе.
Конструктор фасада принимает корневой элемент целого графа объектов, в противном случае он выглядит
так же, как адаптер.
Пример из реальной жизни - JAXB Marshalling Adapter . Назначение этого адаптера - сопоставление простого плоского класса с более сложной структурой, необходимой извне, и для предотвращения «загрязнения» предметного класса чрезмерными аннотациями.