Proxy (шаблон проектирования)
Материал из Seo Wiki - Поисковая Оптимизация и Программирование
Шаблон Proxy (Заместитель) — Шаблон проектирования. Предоставляет объект, который контролирует доступ к другому объекту через перехват всех вызовов.
Содержание |
[править] Цель
[править] Проблема
Необходимо управлять доступом к объекту, так чтобы создавать громоздкие объекты «по требованию».
[править] Решение
Создать суррогат громоздкого объекта. «Заместитель» хранит ссылку, которая позволяет заместителю обратиться к реальному субъекту (объект класса «Заместитель» может обращаться к объекту класса «Субъект», если интерфейсы «Реального Субъекта» и «Субъекта» одинаковы). Поскольку интерфейс «Реального Субъекта» идентичен интерфейсу «Субъекта», так, что «Заместителя» можно подставить вместо «Реального Субъекта», контролирует доступ к «Реальному Субъекту», может отвечать за создание или удаление «Реального Субъекта». «Субъект» определяет общий для «Реального Субъекта» и «Заместителя» интерфейс, так, что «Заместитель» может быть использован везде, где ожидается «Реальный Субъект». При необходимости запросы могут быть переадресованы «Заместителем» «Реальному Субъекту».
Шаблон proxy бывает нескольких видов, а именно:
- Удаленный: обеспечивает связь с «Субъектом» который находится в другом адресном пространстве или на удалённой машине. Так же может отвечать за кодирование запроса и его аргументов и отправку закодированного запроса реальному «Субъекту»,
- Виртуальный: Обеспечивает создание реального «Субъекта» только тогда, когда он действительно понадобится. Так же может кэшировать часть информации о реальном «Субъекте», чтобы отложить его создание,
- Копировать-при-записи:: Обеспечивает копирование «субъекта» при выполнении клиентом определённых действий. Частный случай «виртуального прокси»
- Защищающий: может проверять, имеет ли вызывающий объект необходимые для выполнения запроса права.
- Кэширующий прокси: Обеспечивает временное хранение результатов расчёта до отдачи множественным клиентам, которые могут разделить эти результаты.
- Экранирующий прокси: Защищает «Субъект» от опасных клиентов (или наоборот).
- Синхронизирующий прокси: Производит синхронизированный контроль доступа к «Субъекту» в асинхронной многопоточной среде.
- Smart reference proxy: Производит дополнительные действия когда на «Субъект» создается ссылка, например рассчитывает количество активных ссылок на «Субъект».
[править] Плюсы
- удаленный заместитель;
- виртуальный заместитель может выполнять оптимизацию;
- защищающий заместитель;
- "умная" ссылка;
[править] Минусы
- резкое увеличение времени отклика.
[править] Применимость
Шаблон Proxy может применяться в таких случаях работы с сетевым соединением, огромным объектом в памяти (или на диске) или любым другим ресурсом который сложно или тяжело копировать. Хорошо известный пример применения — объект подсчитывающий число ссылок.
[править] Примеры
[править] 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); } }
[править] C++
/** * "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; }
[править] C#
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> /// <li> /// <lu>определяет общий для <see cref="Math"/> и <see cref="Proxy"/> интерфейс, так что класс /// <see cref="Proxy"/> можно использовать везде, где ожидается <see cref="Math"/></lu> /// </li> /// </remarks> public interface IMath { double Add(double x, double y); double Sub(double x, double y); double Mul(double x, double y); double Div(double x, double y); } /// <summary> /// RealSubject - реальный объект /// </summary> /// <remarks> /// <li> /// <lu>определяет реальный объект, представленный заместителем</lu> /// </li> /// </remarks> class Math : IMath { public Math() { Console.WriteLine("Create object Math. Wait..."); Thread.Sleep(1000); } 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;} } /// <summary> /// Proxy - заместитель /// </summary> /// <remarks> /// <li> /// <lu>хранит ссылку, которая позволяет заместителю обратиться к реальному /// субъекту. Объект класса <see cref="MathProxy"/> может обращаться к объекту класса /// <see cref="IMath"/>, если интерфейсы классов <see cref="Math"/> и <see cref="IMath"/> одинаковы;</lu> /// <lu>предоставляет интерфейс, идентичный интерфейсу <see cref="IMath"/>, так что заместитель /// всегда может быть предоставлен вместо реального субъекта;</lu> /// <lu>контролирует доступ к реальному субъекту и может отвечать за его создание /// и удаление;</lu> /// <lu>прочие обязанности зависят от вида заместителя: /// <li> /// <lu><b>удаленный заместитель</b> отвечает за кодирование запроса и его аргументов /// и отправление закодированного запроса реальному субъекту в /// другом адресном пространстве;</lu> /// <lu><b>виртуальный заместитель</b> может кэшировать дополнительную информацию /// о реальном субъекте, чтобы отложить его создание.</lu> /// <lu><b>защищающий заместитель</b> проверяет, имеет ли вызывающий объект /// необходимые для выполнения запроса права;</lu> /// </li> /// </lu> /// </li> /// </remarks> class MathProxy : IMath { Math math; public MathProxy() { math = null; } /// <summary> /// Быстрая операция - не требует реального субъекта /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public double Add(double x, double y) { return x + y; } public double Sub(double x, double y) { return x - y; } /// <summary> /// Медленная операция - требует создания реального субъекта /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public double Mul(double x, double y) { if (math == null) math = new Math(); return math.Mul(x, y); } public double Div(double x, double y) { if (math == null) math = new Math(); return math.Div(x, y); } }
[править] 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
[править] Object Pascal
[править] См. также
[править] Литература
| структурные шаблоны проектирования |
|
адаптер | мост | компоновщик | декоратор | фасад | заместитель | приспособленец | Выделение частного класса данных |
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:Замісник (шаблон проектування)