Proxy (шаблон проектирования)
Шаблон Proxy (Заместитель) — Шаблон проектирования. Предоставляет объект, который контролирует доступ к другому объекту через перехват всех вызовов.
Цель
Проблема
Необходимо управлять доступом к объекту, так чтобы создавать громоздкие объекты «по требованию».
Решение
Создать суррогат громоздкого объекта. «Заместитель» хранит ссылку, которая позволяет заместителю обратиться к реальному субъекту (объект класса «Заместитель» может обращаться к объекту класса «Субъект», если интерфейсы «Реального Субъекта» и «Субъекта» одинаковы). Поскольку интерфейс «Реального Субъекта» идентичен интерфейсу «Субъекта», так, что «Заместителя» можно подставить вместо «Реального Субъекта», контролирует доступ к «Реальному Субъекту», может отвечать за создание или удаление «Реального Субъекта». «Субъект» определяет общий для «Реального Субъекта» и «Заместителя» интерфейс, так, что «Заместитель» может быть использован везде, где ожидается «Реальный Субъект». При необходимости запросы могут быть переадресованы «Заместителем» «Реальному Субъекту».
Диаграмма классов шаблона проектирования Proxy
Шаблон proxy бывает нескольких видов, а именно:
- Удаленный: обеспечивает связь с «Субъектом» который находится в другом адресном пространстве или на удалённой машине. Так же может отвечать за кодирование запроса и его аргументов и отправку закодированного запроса реальному «Субъекту»,
- Виртуальный: Обеспечивает создание реального «Субъекта» только тогда, когда он действительно понадобится. Так же может кэшировать часть информации о реальном «Субъекте», чтобы отложить его создание,
- Копировать-при-записи:: Обеспечивает копирование «субъекта» при выполнении клиентом определённых действий. Частный случай «виртуального прокси»
- Защищающий: может проверять, имеет ли вызывающий объект необходимые для выполнения запроса права.
- Кэширующий прокси: Обеспечивает временное хранение результатов расчёта до отдачи множественным клиентам, которые могут разделить эти результаты.
- Экранирующий прокси: Защищает «Субъект» от опасных клиентов (или наоборот).
- Синхронизирующий прокси: Производит синхронизированный контроль доступа к «Субъекту» в асинхронной многопоточной среде.
- Smart reference proxy: Производит дополнительные действия когда на «Субъект» создается ссылка, например рассчитывает количество активных ссылок на «Субъект».
Плюсы
- удаленный заместитель;
- виртуальный заместитель может выполнять оптимизацию;
- защищающий заместитель;
- "умная" ссылка;
Минусы
- резкое увеличение времени отклика.
Применимость
Шаблон Proxy может применяться в таких случаях работы с сетевым соединением, огромным объектом в памяти (или на диске) или любым другим ресурсом который сложно или тяжело копировать. Хорошо известный пример применения — объект подсчитывающий число ссылок.
Примеры
Java
<source lang="java"> public class Main {
public static void main(String[] args) { // Create math proxy IMath p = new MathProxy();
// Do the math System.out.println("4 + 2 = " + p.add(4, 2)); System.out.println("4 - 2 = " + p.sub(4, 2)); System.out.println("4 * 2 = " + p.mul(4, 2)); System.out.println("4 / 2 = " + p.div(4, 2)); } }
/**
* "Subject" */
public interface IMath {
public double add(double x, double y);
public double sub(double x, double y);
public double mul(double x, double y);
public double div(double x, double y); }
/**
* "Real Subject" */
public class Math implements IMath {
public double add(double x, double y) { return x + y; }
public double sub(double x, double y) { return x - y; }
public double mul(double x, double y) { return x * y; }
public double div(double x, double y) { return x / y; }
}
/**
* "Proxy Object" */
public class MathProxy implements IMath {
private Math math;
public MathProxy() { math = new Math(); }
public double add(double x, double y) { return math.add(x, y); }
public double sub(double x, double y) { return math.sub(x, y); }
public double mul(double x, double y) { return math.mul(x, y); }
public double div(double x, double y) { return math.div(x, y); } } </source>
C++
<source lang="cpp"> /**
* "Subject" */
class IMath { public:
virtual double add(double x, double y) = 0; virtual double sub(double x, double y) = 0; virtual double mul(double x, double y) = 0; virtual double div(double x, double y) = 0;
};
/**
* "Real Subject" */
class Math : public IMath { public:
double add(double x, double y) {
return x + y;
}
double sub(double x, double y) {
return x - y;
}
double mul(double x, double y) {
return x * y;
}
double div(double x, double y) {
return x / y;
}
};
/**
* "Proxy Object" */
class MathProxy : public IMath { public:
double add(double x, double y) {
return math.add(x, y);
}
double sub(double x, double y) {
return math.sub(x, y);
}
double mul(double x, double y) {
return math.mul(x, y);
}
double div(double x, double y) {
return math.div(x, y);
}
private:
Math math;
};
- include <iostream>
using std::cout; using std::endl;
int main() {
// Create math proxy MathProxy p; // Do the math cout << "4 + 2 = " << p.add(4, 2) << endl; cout << "4 - 2 = " << p.sub(4, 2) << endl; cout << "4 * 2 = " << p.mul(4, 2) << endl; cout << "4 / 2 = " << p.div(4, 2) << endl; return 0;
} </source>
C#
<source lang="csharp">
using System; using System.Threading;
class MainApp
{
static void Main()
{
// Create math proxy
IMath p = new MathProxy();
// Do the math
Console.WriteLine("4 + 2 = " + p.Add(4, 2));
Console.WriteLine("4 - 2 = " + p.Sub(4, 2));
Console.WriteLine("4 * 2 = " + p.Mul(4, 2));
Console.WriteLine("4 / 2 = " + p.Div(4, 2));
// Wait for user
Console.Read();
}
}
/// <summary> /// Subject - субъект /// </summary> /// <remarks>///
JavaScript
<source lang="javascript"> /* Subject */ function IMath() { this.add = function(x, y) {}; this.sub = function(x, y) {}; }
/* Real Subject */ function RMath() { /* IMath.call(this); // агрегируем IMath, т.к. нативного наследования нет // этот вариант следует использовать вместо прототипирования, // если в IMath имеются приватные переменные, // которые могут быть доступны через геттеры в IMath */ this.add = function(x, y) { return x + y; }; this.sub = function(x, y) { return x - y; }; } RMath.prototype = new IMath(); RMath.prototype.constructor = RMath;
/* Proxy */ function MathProxy() { var math = new RMath();
this.add = function(x, y) { return math.add(x, y); }; this.sub = function(x, y) { return math.sub(x, y); }; }
var test = new MathProxy(); alert(test.add(3, 2)); // 5 alert(test.sub(3, 2)); // 1 </source>
Object Pascal
См. также
Литература
| структурные шаблоны проектирования |
|
адаптер | мост | компоновщик | декоратор | фасад | заместитель | приспособленец | Выделение частного класса данных |
ar:نمط الوكيل bg:Пълномощно (шаблон) ca:Proxy (patró de disseny) de:Stellvertreter (Entwurfsmuster) en:Proxy pattern es:Proxy (patrón de diseño) fr:Proxy (patron de conception) it:Proxy pattern ja:Proxy パターン lt:Proxy (objektas) pl:Pełnomocnik (wzorzec projektowy) pt:Proxy (padrões de projeto) uk:Замісник (шаблон проектування)
Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....