НЕ МОЛЧИ!!!    Сделай что-нибудь, чтобы остановить войну России в Украине.
...бойтесь людей равнодушных - именно с их молчаливого согласия происходят все самые ужасные преступления на свете.   ("Репортаж с петлёй на шее")

Шаблон проектирования Proxy (Прокси)

Рассматривается структурный шаблон проектирования Proxy, приведено описание шаблона и пример реализации.

Содержание

  • Область применения
  • Реализация
  • Итоги

У этого шаблона несколько имен: Proxy, Прокси, Заместитель. Мне больше нравится называть его proxy. Шаблон проектирования Прокси очень похож на рассмотренный ранее структурный шаблон проектирования Декоратор. Но если последний используют, чтобы расширить функции заменяемого класса, то у нашего другие задачи.

Область применения

Шаблон Proxy, как можно догадаться из названия, предполагает наличие промежуточного объекта, стоящего перед основным объектом. Прокси-объект должен содержать ссылку на основной объект и иметь аналогичный с ним интерфейс. Это позволяет возложить на него достаточно много дополнительных обязанностей, вот некоторые из них:

  • управлять доступом к основному объекту в зависимости от прав доступа;
  • замещать основной объект в некоторых случаях, например для экономии ресурсов сервера. Чаще всего при этом proxy берет на себя часть простых функций основного объекта, а оригинал создается только тогда, когда необходим ответ на «тяжелые» запросы;
  • с помощью промежуточного proxy можно вводить дополнительный функционал, если сложно или нет возможности изменить основной объект.

И это, конечно, только некоторые возможности данного шаблона. Они определяются задачами проектирования и ограничены лишь вашей фантазией.

Реализация

Рассмотрим случай, когда с помощью Proxy шаблона хотят уменьшить нагрузку сервера. В примере реальный объект класса Math производит математические вычисления, а с помощью Прокси у него «забирают» часть простых функций откладывая тем самым создание объекта математической библиотеки.
Итак, создаем основной объект.

//определяем реализуемый интерфейс 
interface IMath
{
    public function add($operand1, $operand2);
    
    public function subj($operand1, $operand2);

    public function mul($operand1, $operand2);

    public function div($operand1, $operand2);

}

//определяем реальный объект
class Math implements IMath
{
    public function add($oper1, $oper2)
    {
        return $oper1 + $oper2;
    }

    public function subj($oper1, $oper2)
    {
        return $oper1 - $oper2;
    }

    public function mul($oper1, $oper2)
    {
        return $oper1 * $oper2;
    }

    public function div($oper1, $oper2)
    {
        return $oper1 / $oper2;
    }
}

Теперь определим наш прокси-объект, который будет выполнять операции сложения и вычитания самостоятельно, а умножение и деление переадресовать подменяемому объекту.

class MathProxy implements IMath
{
    protected $math = null;

    public function add($oper1, $oper2)
    {
        return $oper1 + $oper2;
    }

    public function subj($oper1, $oper2)
    {
        return $oper1 - $oper2;
    }

    public function mul($oper1, $oper2)
    {
        if ($this->math === null) {
            $this->math = new Math();
        } 
        return $this->math->mul($oper1, $oper2);
    }

    public function div($oper1, $oper2)
    {
        if ($this->math === null) {
            $this->math = new Math();
        } 
        return $this->math->div($oper1, $oper2);
    }
}

Итоги

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

Перейти к списку шаблонов проектирования.