/* */
НЕ МОЛЧИ!!!    Делай что-нибудь, чтобы остановить войну России в Украине.
Бойтесь равнодушных — они не убивают и не предают, но только с их молчаливого согласия существует на земле предательство и убийство.

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

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

У этого шаблона несколько имен: 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);
    }
}

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