Паттерн «Заместитель» («Proxy»). Описание и использование (на примере Delphi)

Если программа включает в себя достаточно «тяжёлые» объекты, которые потребляют достаточно много ресурсов, наиболее оптимальное решение – создавать такие объекты «по запросу». То есть тогда, когда они на самом деле необходимы.

Для решения этой задачи и предназначен паттерн «Заместитель».

 Описание

Паттерн «Заместитель» является своего суррогатом другого объекта и контролирует доступ к нему [1].

По сути, «Заместитель» представляет собой своего рода «заглушку», которая помещается в том месте программного кода, где необходимо вызвать «тяжелый» объект. Так как «Заместитель» потребляет значительно меньше ресурсов, то при начальной инициализации получается их значительная экономия. Когда нужно вызвать непосредственно сам объект, достаточно просто отправить соответствующий запрос «Заместителю».

В качестве примера можно привести получение объекта содержащего массив сведений из базы данных тогда, когда он действительно необходим.

Ниже представлена диаграмма классов паттерна «Заместитель».

Паттерн "Заместитель" диаграмма классов

Паттерн «Заместитель» состоит из трёх участников.

  • RealSubject – Реальный субъект. Определяет реальный объект представленный заместителем;
  • Proxy – собственно «заместитель»;
  • Subject – субъект. Определяет общий интерфейс для RealSubject и Proxy. Благодаря этому и становится возможным использование Proxy там, где ожидается RealSubject.
    Может быть реализован в виде абстрактного базового класса или интерфейса.

Класс Proxy выполняет следующие функции:

  • Хранит ссылку, которая позволяет обратиться к реальному субъекту;
  • Предоставляет интерфейс аналогичный интерфейсу реального субъекта. Поэтому класс Proxy всегда может быть подставлен вместо реального субъекта;
  • Контролирует доступ к реальному субъекту и может отвечать за его создание и удаление.
Пример использования

В качестве примера реализации паттерна «Заместитель» рассмотрим простой калькулятор на Delphi.

Создадим абстрактный класс Calc в котором объявим методы для арифметических операций сложения, вычитания, умножения и деления. Затем класс RealCalc, в котором все эти методы будут реализованы. И, наконец, класс CalcProxy, который будет служить «Заместителем» для класса RealCalc.

Код модуля со всеми тремя классами приведён ниже.

[stextbox id=»info» caption=»Примечание»]

В старых версиях Delphi отсутствует поддержка классических абстрактных классов. Поэтому при работе со старыми версиями Delphi базовый класс необходимо объявить как обычный класс с абстрактными методами.[/stextbox]

Для того чтобы подставить заместитель вместо реального субъекта нужно объявить переменную (или поле класса) типа субъект.

 А, затем инициализировать её «Заместителем».

 После этого во всех случаях использования данной переменной программа будет работать с «Заместителем». Для наглядности приведём фрагмент возможной реализации работы с данным модулем, в которой арифметические вычисления осуществляются путём нажатия на соответствующие кнопки.

 Контроль доступа к реальному объекту

«Заместитель» также может реализовывать контроль доступа к замещаемому им объекту (реальному субъекту).

Можно включить в код «Заместителя» алгоритмы, которые в зависимости от определённых условий, либо предоставляют доступ к реальному субъекту либо отклоняют запрос.

Для примера, усовершенствуем метод деления в классе CalcProxy и запретим деление на ноль.

 В результате такой модификации, если параметр b будет равен нулю, возникнет исключительная ситуация и пользователь увидит на экране сообщение «Делить на ноль нельзя!».

К слову, не смотря на то, что эта функция работает с вещественным типом данных, приведённый код реально работает.

Можно написать, например, следующий код и проверить.

 В зависимости от конкретной задачи «Заместитель» вполне может и более сложные проверки (проверка уровня прав пользователя и т.д.).

Таким образом, паттерн «Заместитель» позволяет не только оптимизировать использование ресурсов ЭВМ при начальной инициализации программы, но и управлять доступом к замещаемому объекту инкапсулируя соответствующие алгоритмы.

Источники:
  1. Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж. Приёмы объектно-ориентированного проектирования. Паттерны проектирования.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *