Заместитель (Proxy)
реализации: java, количество: 4
реализации(исходники)
+добавить
Заместитель - паттерн, контролирующий доступ к объектам, предоставляя более оптимальное их взаимодействие. оригинал codelab.ru codelab.ru источник
Условия, Задача, Назначение
Разумно управлять доступом к объекту, поскольку тогда можно отложить расходы на создание и инициализацию до момента, когда объект действительно понадобится. Одна из ключевых причин использования данного паттерна. Главная идея – не переписывая, не вмешиваясь в код некой цельной системы обеспечить более оптимальное и экономичное взаимодействие участников этой системы. оригинал codelab.ru источник codelab.ruТаким образом, сначала выявляются узкие места, затем объекты, функционирование которых проходит не совсем оптимально, и вводятся эти самые объекты заместители (proxy), которые, дублируя интерфейс «проблемных» объектов, переадресовывают им вызовы клиента лишь тогда, когда это действительно необходимо, либо после некоторых оптимизационных действий. В результате, не делая никаких изменений в архитектуре системы, мы получаем немалые возможности по улучшению качества функционирования.
Мотивация
Рассмотрим редактор документов, который допускает встраивание в документ графических объектов. Затраты на создание некоторых таких объектов, например больших растровых изображений, могут быть весьма значительны. Но документ должен открываться быстро, поэтому следует избегать создания всех «тяжелых» объектов на стадии открытия (да и вообще это излишне, поскольку не все они будут видны одновременно).В связи с такими ограничениями кажется разумным создавать «тяжелые» объекты по требованию. Это означает «когда изображение становится видимым». Но что поместить в документ вместо изображения? И как, не усложняя реализации редактора, скрыть то, что изображение создается по требованию? Например, оптимизация не должна отражаться на коде, отвечающем за рисование и форматирование (т.е. не должна никак меняться архитектура).
Решение состоит в том, чтобы использовать другой объект – заместитель изображения, который временно подставляется вместо реального изображения. Заместитель ведет себя точно так же, как само изображение, и выполняет при необходимости его инстанцирование.
codelab.ru источник оригинал codelab.ru
оригинал codelab.ru codelab.ru источник
На следующей диаграмме классов этот пример показан более подробно. codelab.ru источник codelab.ru оригинал
оригинал источник codelab.ru codelab.ru
В объекте ImageProxy находятся также ограничивающий прямоугольник изображения и ссылка на экземпляр реального объекта Image. Ссылка остается недействительной, пока заместитель не инстанцирует реальное изображение. Операцией Draw гарантируется, что изображение будет создано до того, как заместитель переадресует ему запрос. Операция GetExtent переадресует запрос изображению, только если оно уже инстанцировано, в противном случае ImageProxy возвращает размеры пустого прямоугольника, которые хранит сам. оригинал codelab.ru источник codelab.ru
Признаки применения, использования паттерна Заместитель (Proxy)
Паттерн заместитель применим во всех случаях, когда возникает необходимость сослаться на объект более изощренно, чем это возможно, если использовать простую ссылку. Вот несколько типичных ситуаций, где заместитель оказывается полезным: источник codelab.ru оригинал codelab.ru- Когда требуется удаленный функционал.
Удаленный заместитель предоставляет локального представителя локального представителя вместо целевого объекта, находящегося в другом адресном пространстве. В реализации известного интерфейса удаленного взаимодействия RMI языка Java используется именно этот подход. codelab.ru источник оригинал codelab.ru - Когда нужен виртуальный заместитель.
Виртуальный заместитель создает «тяжелые» объекты по требованию. Примером может служить класс ImageProxy, описанный ранее. оригинал источник codelab.ru codelab.ru - Когда нужно контролировать доступ к исходному объекту.
Защищающий заместитель контролирует доступ к исходному объекту. Такие заместители полезны, когда для разных объектов определены различные права доступа. Например, в операционной системе Choices объекты Kernel Proxy ограничивают права доступа к объектам операционной системы. источник codelab.ru оригинал codelab.ru - Когда нужно выполнять дополнительные действия при доступе к объекту.
«Умная ссылка» - это замена обычного указателя. Она позволяет выполнить дополнительные действия при доступе к объекту. К типичным применениям такой ссылки можно отнести:
- подсчет числа ссылок на реальный объект, с тем, чтобы занимаемую им память можно было освободить автоматически, когда не останется ни одной ссылки (такие ссылки называют еще «умными» указателями);
- загрузку объекта в память при первом обращении к нему;
- проверку и установку блокировки на реальный объект при обращении к нему, чтобы никакой другой объект не смог в это время изменить его.
- и т.д. codelab.ru источник оригинал codelab.ru
Решение
оригинал codelab.ru codelab.ru источник
источник codelab.ru оригинал codelab.ru
Вот как может выглядеть диаграмма объектов для структуры с заместителем во время выполнения: оригинал codelab.ru источник codelab.ru
источник codelab.ru codelab.ru оригинал
- Proxy (imageProxy) – заместитель,
Хранит ссылку, которая позволяет заместителю обратиться к реальному субъекту, используя тот же интерфейс класса Subject.
Предоставляет интерфейс, идентичный интерфейсу Subject, так что заместитель всегда может быть подставлен вместо реального субъекта.
Контролирует доступ к реальному субъекту и может отвечать за его создание и удаление.
Выполняет прочие обязанности - зависит от вида заместителя.
Удаленный заместитель отвечает за кодирование запроса и его аргументов и отправление закодированного запроса реальному субъекту в другом адресном пространстве (Java RMI).
Виртуальный заместитель может кэшировать дополнительную информацию о реальном субъекте, чтобы отложить его создание. Например, класс ImageProxy кэширует размеры реального изображения.
Защищающий заместитель проверяет, имеет ли вызывающий объект необходимые для выполнения запроса права. codelab.ru оригинал codelab.ru источник - Subject (Graphic) – субъект.
Определяет общий для RealSubject и Proxy интерфейс, так что класс Proxy можно использовать везде, где ожидается RealSubject; codelab.ru оригинал источник codelab.ru - RealSubject (Image) - реальный субъект.
Определяет реальный объект, представленный заместителем. источник codelab.ru оригинал codelab.ru
Схема использования паттерна Заместитель (Proxy)
Proxy при необходимости переадресует запросы объекту RealSubject. Детали зависят от вида заместителя. Либо запросы переадресовываются после выполнения некоторых действий по оптимизации. Детали опять же зависят от вида заместителя. источник оригинал codelab.ru codelab.ru
Вопросы, касающиеся реализации паттерна Заместитель (Proxy)
При реализации паттерна заместитель можно использовать следующие возможности языка: codelab.ru codelab.ru источник оригинал- Перегрузка оператора доступа к членам в C++.
Язык C++ поддерживает перегрузку оператора доступа к членам класса “->”. Это позволяет производить дополнительные действия при любом разыменовании указателя на объект. Для реализации некоторых видов заместителей это оказывается полезно, поскольку заместитель ведет себя аналогично указателю.
Но перегрузка оператора доступа - лучшее решение далеко не для всех видов заместителей. Некоторым из них должно быть точно известно, какая операция вызывается, а в таких случаях перегрузка оператора доступа не работает. Рассмотрим пример виртуального заместителя такого как ImageProxy. Изображение нужно загружать в точно определенное время - при вызове операции Draw, а не при каждом обращении к нему. Перегрузка оператора доступа не позволяет различить подобные случаи. В такой ситуации придется вручную реализовать каждую операцию заместителя, переадресующую запрос субъекту.
Обычно все эти операции очень похожи друг на друга. Они проверяют, что запрос корректен, что объект-адресат существует и т.д., а потом уже перенаправляют ему запрос. Писать этот код снова и снова надоедает. Поэтому нередко для его автоматической генерации используют препроцессор. codelab.ru codelab.ru источник оригинал - Метод doesNotUnderstand в Smalltalk.
В языке Smalltalk есть возможность, позволяющая автоматически поддержать переадресацию запросов. При отправлении клиентом сообщения, для которого у получателя нет соответствующего метода, Smalltalk вызывает метод doesNotUnderstand: aMessage.
Заместитель может переопределить doesNotUnderstand так, что сообщение будет переадресовано субъекту.
Дабы гарантировать, что запрос будет перенаправлен субъекту, а не просто тихо поглощен заместителем, класс Proxy можно определить так, что он не станет понимать никаких сообщений. Smalltalk позволяет это сделать, надо лишь, чтобы у Proxy не было суперкласса.
Главный недостаток метода doesNotUnderstand: в том, что в большинстве Smalltalk-систем имеется несколько специальных сообщений, обрабатываемых непосредственно виртуальной машиной, а в этом случае стандартный механизм поиска методов обходится. Правда, единственной такой операцией, написанной в классе Ob j ect (следовательно, могущей затронуть заместителей), является тождество ==.
Если вы собираетесь применять doesNotUnderstand: для реализация заместителя, то должны как-то решить вышеописанную проблему. Нельзя же ожидать, что совпадение заместителей - это то же самое, что и совпадение реальных субъектов. К сожалению, doesNotUnderstand: изначально создавался для обработки ошибок, а не для построения заместителей, поэтому его быстродействие оставляет желать лучшего. источник codelab.ru оригинал codelab.ru - Заместителю не всегда должен быть известен тип реального объекта.
Если класс Proxy может работать с субъектом только через его абстрактный интерфейс, то не нужно создавать Proxy для каждого класса реального субъекта RealSubject; заместитель может обращаться к любому из них единообразно. Но если заместитель должен инстанцировать реальных субъектов (как обстоит дело в случае виртуальных заместителей), то знание конкретного класса обязательно, либо опять же – использование абстрактной фабрики. источник оригинал codelab.ru codelab.ru
Результаты
С помощью паттерна заместитель при доступе к объекту вводится дополнительный уровень косвенности. У этого подхода есть много вариантов в зависимости от вида заместителя: источник codelab.ru оригинал codelab.ru- Удаленный заместитель инкапсулирует тот факт, что объект находится в другом адресном пространстве; codelab.ru оригинал codelab.ru источник
- Виртуальный заместитель может выполнять оптимизацию, например создание объекта по требованию; источник оригинал codelab.ru codelab.ru
- Защищающий заместитель и «умная» ссылка позволяют решать дополнительные задачи (оптимизации) при доступе к объекту. codelab.ru оригинал codelab.ru источник



