Я смотрел на Proxy Pattern, и мне он кажется очень похожим на паттерны Decorator, Adapter и Bridge. Я что-то неправильно понимаю? Какая разница? Зачем мне использовать шаблон Proxy по сравнению с другими? Как вы использовали их в прошлом в реальных проектах?
design-patterns
decorator
bridge
proxy-pattern
Чарльз Грэм
источник
источник
Ответы:
Прокси, Декоратор, Адаптер и Мост - все это варианты «обёртывания» класса. Но их использование отличается.
Прокси-сервер можно использовать, когда вы хотите создать отложенный экземпляр объекта или скрыть тот факт, что вы вызываете удаленную службу, или контролировать доступ к объекту.
Декоратор также называется «Smart Proxy». Это используется, когда вы хотите добавить функциональность к объекту, но не расширять тип этого объекта. Это позволяет вам делать это во время выполнения.
Адаптер используется, когда у вас есть абстрактный интерфейс, и вы хотите отобразить этот интерфейс на другой объект, который имеет аналогичную функциональную роль, но другой интерфейс.
Bridge очень похож на Adapter, но мы называем его Bridge, когда вы определяете как абстрактный интерфейс, так и базовую реализацию. Т.е. вы не адаптируетесь к какому-либо унаследованному или стороннему коду, вы являетесь разработчиком всего кода, но вам нужно иметь возможность менять различные реализации.
Фасад - это высокоуровневый (читай: более простой) интерфейс для подсистемы одного или нескольких классов. Предположим, у вас есть сложная концепция, которая требует представления нескольких объектов. Внесение изменений в этот набор объектов сбивает с толку, потому что вы не всегда знаете, какой объект имеет метод, который вам нужно вызвать. Настало время написать Facade, который предоставляет высокоуровневые методы для всех сложных операций, которые вы можете выполнять с коллекцией объектов. Пример: Модель предметной области для школьной секции, с помощью методов , таких как
countStudents()
,reportAttendance()
,assignSubstituteTeacher()
, и так далее.источник
Как говорится в ответе Билла, их варианты использования различны .
Как и их структуры.
Прокси и Декоратор имеют тот же интерфейс, что и их обернутые типы, но прокси создает экземпляр под капотом, тогда как декоратор берет экземпляр в конструкторе.
Adapter и Facade имеют интерфейс, отличный от того, что они обертывают. Но адаптер происходит от существующего интерфейса, тогда как фасад создает новый интерфейс.
Мост и адаптер указывают на существующий тип. Но мост будет указывать на абстрактный тип, а адаптер может указывать на конкретный тип. Мост позволит вам выполнить сопряжение реализации во время выполнения, тогда как адаптер обычно не будет.
источник
Мой взгляд на предмет.
Все четыре шаблона имеют много общего, все четыре иногда неофициально называют обертками, или обертками. Все используют композицию, переносят тему и делегируют выполнение субъекту в какой-то момент, отображая один вызов метода на другой. Они избавляют клиента от необходимости создавать другой объект и копировать все соответствующие данные. При разумном использовании они экономят память и процессор.
Продвигая слабую связь, они делают когда-то стабильный код менее подверженным неизбежным изменениям и лучше читаемым для других разработчиков.
адаптер
Адаптер адаптирует предмет (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 . Назначение этого адаптера - сопоставление простого плоского класса с более сложной структурой, необходимой извне, и для предотвращения «загрязнения» предметного класса чрезмерными аннотациями.
источник
Существует много совпадений во многих шаблонах GoF. Все они построены на силе полиморфизма и иногда действительно различаются только намерениями. (стратегия против государства)
Мое понимание шаблонов увеличилось в 100 раз после прочтения Head First Design Patterns .
Я очень рекомендую это!
источник
Все хорошие ответы экспертов уже объяснили, что означает каждая модель.
Я украслю ключевые моменты.
Decorator:
например (с цепочкой):
java.io
классы пакетов, связанные сInputStream
&OutputStream
интерфейсамПрокси-сервер:
например:
java.rmi
пакеты классов.адаптер:
например
java.io.InputStreamReader
(InputStream
возвращаетReader
)мост:
например, коллекции классов в
java.util
.List
осуществляетсяArrayList
.Ключевые примечания:
Посмотрите на отличные вопросы / статьи по SE, касающиеся примеров различных шаблонов дизайна.
Когда использовать шаблон декоратора?
Когда вы используете шаблон моста? Чем он отличается от шаблона адаптера?
Различия между прокси и шаблоном декоратора
источник
Они очень похожи, а линии между ними довольно серые. Я предлагаю вам прочитать записи « Прокси шаблон» и « Шаблон декоратора» в вики c2.
Записи и обсуждения там довольно обширны, и они также ссылаются на другие соответствующие статьи. Кстати, c2 wiki отлично подходит для размышлений о нюансах между различными шаблонами.
Чтобы суммировать записи c2, я бы сказал, что декоратор добавляет / изменяет поведение, но прокси имеет больше общего с контролем доступа (ленивая реализация, удаленный доступ, безопасность и т. Д.). Но, как я уже сказал, линии между ними серые, и я вижу ссылки на прокси, которые можно легко рассматривать как декораторы, и наоборот.
источник
Все четыре шаблона предполагают наложение внутреннего объекта / класса на внешний, поэтому они очень похожи по структуре. Я бы обозначил разницу по цели:
И путем изменения интерфейса между внутренними и внешними объектами:
источник
Это цитата из Head First Design Patterns
Определения принадлежит книге. Примеры принадлежат мне.
Декоратор - не изменяет интерфейс, но добавляет ответственность. Предположим, у вас есть автомобильный интерфейс, когда вы реализуете это для другой модели автомобиля (s, sv, sl), вам может потребоваться добавить больше ответственности для некоторых моделей. Как есть люк, подушка безопасности и т.д ..
Адаптер - конвертирует один интерфейс в другой. У вас есть автомобильный интерфейс, и вы хотели бы, чтобы он действовал как джип. Итак, вы берете машину, модифицируете ее и превращаетесь в джип. Так как это не настоящий джип. Но действует как джип.
Фасад - упрощает интерфейс. Предположим, у вас есть интерфейс автомобиля, самолета, корабля. На самом деле все, что вам нужно, это класс, который отправляет людей из одного места в другое. Вы хотите, чтобы фасад решал, какой автомобиль использовать. Затем вы собираете все эти ссылки на интерфейсы под 1 зонтиком и позволяете ему решить / делегировать для простоты.
Глава первая: «Фасад не только упрощает интерфейс, он отделяет клиента от подсистемы компонентов. Фасады и адаптеры могут объединять несколько классов, но цель фасада состоит в том, чтобы упростить, а адаптер - преобразовать интерфейс во что-то другое. "
источник
Я использую его довольно часто при использовании веб-сервисов. Шаблон Proxy, вероятно, следует переименовать во что-то более прагматичное, например, «Шаблон Wrapper». У меня также есть библиотека, которая является прокси-сервером для MS Excel. Это позволяет очень легко автоматизировать Excel, не беспокоясь о таких деталях, как версия установлена (если есть).
источник
Говоря подробно о реализации, я нахожу разницу между Proxy и Decorator, Adapter, Facade ... В обычной реализации этих шаблонов есть целевой объект, обернутый вмещающим объектом. Клиент использует включающий объект вместо целевого объекта. И целевой объект на самом деле играет важную роль в некоторых методах включения объекта.
Тем не менее, в случае Прокси, включающий объект может воспроизводить некоторые методы сам по себе, он просто инициализирует целевой объект, когда клиент вызывает некоторые методы, в которых ему требуется целевой объект, принять участие. Это ленивая инициализация. В случае других шаблонов, окружающий объект фактически основан на целевом объекте. Таким образом, целевой объект всегда инициализируется вместе с включением объекта в конструкторы / сеттеры.
Другое дело, что прокси делает именно то, что делает цель, тогда как другие шаблоны добавляют больше функциональности к цели.
источник
Я хотел бы добавить примеры к ответу Билла Карвинга (кстати, это здорово). Я также добавил некоторые ключевые отличия в реализации, которые, по моему мнению, отсутствуют
Цитируемые части взяты из ответа [ https://stackoverflow.com/a/350471/1984346] (Билл Карвинг)
ProxyClass и ObjectClass, которые проксируются, должны реализовывать один и тот же интерфейс, поэтому они взаимозаменяемы
Пример - прокси дорогой объект
DecoratorClass должен (мог) реализовывать расширенный интерфейс ObjectClass. Таким образом, ObjectClass может быть заменен DecoratorClass, но не наоборот.
Пример - добавление дополнительных функций
Различия в имплантации Прокси, Декоратор, Адаптер
Адаптер предоставляет другой интерфейс для своей темы. Прокси предоставляет тот же интерфейс. Декоратор предоставляет расширенный интерфейс.
Большая часть информации в этом ответе взята с https://sourcemaking.com/design_patterns , которую я рекомендую как отличный ресурс для шаблонов проектирования.
источник
Я верю, что код даст ясные идеи (чтобы дополнить ответы других). Пожалуйста, смотрите ниже, (Сосредоточьтесь на типах, которые класс реализует и переносит)
источник
Шаблон проектирования - это не математика, это сочетание искусства и разработки программного обеспечения. Нет ничего похожего на это требование, вы должны использовать прокси, бридж и т. Д. Для решения проблем создаются шаблоны проектирования. Если вы предвидите проблему с дизайном, используйте ее. Основываясь на опыте, вы узнаете для конкретной проблемы, какой шаблон использовать. Если вы хорошо разбираетесь в основополагающих принципах проектирования, вы бы реализовали шаблон проектирования, не зная, что это шаблон. Типичный пример - паттерны и заводские паттерны.
Следовательно, сконцентрируйтесь больше на основополагающих принципах дизайна, принципах чистого кодирования и ттд
источник