Страницы

Поиск по вопросам

четверг, 19 декабря 2019 г.

В чём отличия и сходства паттернов Adapter, Decorator, Wrapper и Proxy?

#java #шаблоны_проектирования


Здравствуйте. Разбираюсь понемного с паттернами проектирования, и не могу понять
разницу в данных паттернах. В некоторых местах их считают синонимами. Отличия адаптера
и декоратора я вроде бы нашёл (как я понял первый реализует интерфейс отличный, от
интерфейса оборачиваемого объекта; а второй реализует тот же интерфейс, что и оборачиваемый
объект). Но вот чем отличается адаптер от раппера (обёртки) найти не могу. Также не
понятно, чем прокси отличается от декоратора. 
PS Желательны примеры кода, чтобы сразу увидеть отличия и сходства.
    


Ответы

Ответ 1



Сперва маленькое уточнение: Wrapper -- это синоним декоратора. Т.о. речь в вопросе на самом деле идет о трех шаблонах: декоратор, адаптер и заместитель. Все эти шаблоны схожи тем, что создают некоторую "обертку" вокруг класса. Так что ваши слова во многом справедливы: ощущение, что это буквально один нож, которым кто-то режет хлеб, а кто-то строгает дерево, а кто-то - ещё как-то применяет его Однако различаются они тем, какой интерфейс предоставляют и что делают с функциональностью оригинального класса (читай, внешний вид и предназначение ножа). Заместитель (proxy) оборачивает некоторый класс и предоставляет такой же интерфейс. Цель -- "притвориться" оригинальным классом и скрыть от клиента детали. Типичные примеры использования -- ленивая инициализация оборачиваемого класса или оборачивание вызовов стороннего сервиса. Декоратор также оборачивает некоторый класс и предоставляет такой же или расширенный интерфейс. Иногда декоратор называют "умным заместителем" (smart proxy). Т.е. декоратор может притворяться оригинальным классом и при этом расширять его функциональность. Пример: у вас есть заместитель, который прячет вызовы к стороннему сервису. Можно создать декоратор, который будет оборачивать и кэшировать результаты вызовов. Другой пример: нужно расширить функциональность оригинального класса, но он закрыт для наследования. Создается декоратор, который расширяет интерфейс оригинального класса. Адаптер также оборачивает некоторый класс, но при этом предоставляет другой интерфейс. Т.е. используется в случаях, когда есть класс с нужными данными и поведением, но с неподходящим интерфейсом. Итого: --------------------------------------------------------------------------- | Шаблон | Что делает с интерфейсом | Что делает с функциональностью | --------------------------------------------------------------------------- | Заместитель | Не изменяет | Не изменяет | --------------------------------------------------------------------------- | Декоратор | Не изменяет/расширяет | Расширяет | --------------------------------------------------------------------------- | Адаптер | Изменяет | Не изменяет | --------------------------------------------------------------------------- Что касается того, как они выглядят на уровне кода. Реализации, само собой, могут варьироваться, поэтому чтобы определить, что есть что, пользуйтесь следующими шагами: Определите оригинальный объект/класс. Посмотрите, какой интерфейс предоставляет обертка. Посмотрите, какую функциональность предоставляет обертка.

Ответ 2



Декоратор (Wraper) позволяет создать цепочку оберток, и каждая обертка добавляет что-то к исходному объекту. Обогащает его функционал. Было побайтовое чтение, раз и добавили оберткой буферизацию, а потом еще что-нибудь... и т.д. Адаптер - посредник, переходник. Например, конвертировать данные одного формата в другой формат, чтобы две независимые библиотеки могли договориться друг с другом (например, XML и JSON). Proxy - это заместитель (например, как банковский чек замещает пачку наличности). Это дублер, который временно замещает оригинал. очень наглядно и понятно здесь: https://refactoring.guru/ru/design-patterns/catalog

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

Отправить комментарий