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