Заместитель (Proxy)

Метафора

 

Наверняка вы работали когда-нибудь с прокси-серверами? Суть паттерна такая же, есть некоторый прокси объект, который делает перенаправление вызовов к реальному объекту. При этом для Вас как для клиента ничего не меняется, интерфейс остаётся тем же.

 

Назначение

 

Является суррогатом другого объекта и контролирует доступ к нему. Решает проблему контроля доступа к объекту, не изменяя при этом клиента.

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

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

 

Диаграмма

 

Заместитель

Заместитель

 

Пример

 

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

  • Developer

    Указано, что
    » чтение данных в конструкторе, не самое лучшее решение..
    SELECT * FROM spfli INTO CORRESPONDING FIELDS OF TABLE mt_data.»
    К примеру, необходимо выбрать номер рейса, дату из таблицы и присвоить их переменным класса в конструкторе.
    Не подскажите тогда, как можно заменить данное не самое лучшее решение?

    • Именно этим и занимается прокси в примере, решает проблему перенося запрос данных на более поздний срок. Ну а при проектировании своих объектов отложенная инициализация является неплохим подходом. https://ru.m.wikipedia.org/wiki/Отложенная_инициализация

      • svirinstel

        Если абстрагироваться от прокси, то, мое личное мнение, инициализация данных в конструкторе вполне нормальная ситуация, если эти данные необходимы для полноты объекта.
        Пример: класс, описывающий какой-либо документ, который отвечает лишь за получение и обработку данных по нему. Смысл существования такого объекта с ключевыми полями в качестве атрибута, но без основных данных из БД, равен нулю. И в любом случае после создания такого объекта нам придется вызывать его инициализацию…
        Отложенная инициализация имеет место быть, но опять же для ряда случаев. Например, тот же класс (описанный выше) получает доп. функционал в виде удаления записи из БД. В таком случае необязательно получать данные из БД по ключам, однако необходимо в конструкторе выполнить проверку, что такая запись вообще существует. В случае отсутствия — кинуть исключение прямо из конструктора.

  • Кстати, я бы в качестве примера все же сделал lcl_subject интерфейсом, а прокси и реальный объект — его реализацией. Смысла в абстрактном классе нет.
    К тому же, часто приходится именно навешивать прокси, когда уже есть готовый реальный объект, но к нему нужно что-то еще, какой-то доп.функционал.
    Я бы все же для примера взял задачу, когда над вызовом каждого метода реального объекта необходимо добавить запись этого действия в лог. В таком случае это будет реальный пример из жизни, максимально описывающий смысл прокси.
    Вот в этом видео у Немчинского тема прокси отлично раскрыта: https://youtu.be/gCLePmhzy9o?list=PLmqFxxywkatStbd9hdzVOS1hZa9dc56k4