Назначение
Proxy представляет собой искусственный заменитель какого либо существующего объекта, имеющий с этим объектом общий интерфейс и управляющий доступом к нему. Есть три канонических области применения Porxy:
- Remote proxy - для управления доступом к удаленному объекту, который может быть расположен на другом сервере или в другой системе
- Virtual proxy - для управления доступом к объекту, который затартно создавать
- Protection proxy - для управления доступом к объекту в соответствии с правами доступа.
Описание
Допустим, имеется объект, доступом к которому мы хотим управлять. Контракт взаимодействия с этим объектом должен быть выражен в виде интерфейса, который используют клиенты. Для того чтобы управлять доступом к оригинальному объекту мы создаем новую реализацию его интерфейса, называемую proxy, которая имеет у себя ссылку на исходный объект. Proxy объект управляет доступом к проксируемому объекту, при необходимости, делегируя ему вызовы методов.
Proxy не обязан иметь конструктор с аргументом проксируемого объекта (как это делает Decorator), он может сам создавать и кешировать оригинальный объект.
Возможны сложности с equals.
Реализация
Collaboration diagram
Class diagram
- proxy реализует интерфейс проксируемого объекта
- proxy имеет ссылку на проксируемый объект
- proxy может не принимать готовый проксируемый объект, а создавать его в нужный момент из параметров, которые он получил в конструкторе.
Примеры
Допустим, существует класс BookParser
для обработки книг из текстового вида.
Результатом обработки является различные метаданные, полученные в процессе: число
страниц, число слов и т.д. Обработка больших книг занимает много времени, которое
не всегда необходимо. Для того чтобы отложить трудоемкую операцию до тех пор,
пока она не станет гарантировано нужна, можно использовать proxy. Proxy объект
сохраняет в себе исходное строковое представление книги, но не инициализирует
BookParser
до тех пор, пока без него нельзя будет обойтись. Как только происходит
вызов метода, непременно требующий обработки книги, происходит инициализация BookParser
и его кеширование в proxy объекте для того чтобы быстро отвечать на повторные/новые
вызовы.
Варианты
- три основных вида в зависимости от задачи
- конструктор принимает готовый объект, реализующий
Service
- proxy не отвечает сам за создание объекта - конструктор принимает параметры, из которых в нужный момент можно будет сделать
Service
Чем отличается
Adapter – Proxy не изменяет интерфейс объекта (proxy имеет тот же интерфейс, заменителем которого он является), в то время как назначение Adapter как раз в том, чтобы изменить интерфейс таким образом, чтобы он подошел в нужном месте.
Decorator структурно соответствует случаю Proxy, который принимает в конструкторе готовый объект, но отличается от Proxy намерением: Decorator добавляет какой-либо новый функционал или модифицирует существующий, а Proxy предназначен для контроля доступа. Для Decorator типична ситуация, когда Decorator обернут один в другой как луковична кожура, для Proxy, хоть это и возможно, но не типично: редко на одном объекте используется больше одно Proxy.
Ссылки
https://java-design-patterns.com/patterns/proxy/
https://github.com/iluwatar/java-design-patterns/tree/master/proxy
https://refactoring.guru/design-patterns/proxy
Proxy Pattern – Design Patterns (ep 10)