Шаблон Proxy (Заступник) — Шаблон проєктування. Надає об'єкт, що контролює доступ, перехоплюючи всі виклики до нього.
Проблема
Необхідно керувати доступом до об'єкта так, щоб створювати громіздкі об'єкти «на вимогу».
Вирішення
Створити сурогат громіздкого об'єкта. «Заступник» зберігає посилання, яке дозволяє заступникові звернутися до реального суб'єкта (об'єкт класу «Заступник» може звертатися до об'єкта класу «Суб'єкт», якщо інтерфейси «Реального Суб'єкта» і «Суб'єкта» однакові). Оскільки інтерфейс «Реального Суб'єкта» ідентичний інтерфейсу «Суб'єкта», так, що «Заступника» можна підставити замість «Реального Суб'єкта», контролює доступ до «Реального Суб'єкта», може відповідати за створення або видалення «Реального Суб'єкта». «Суб'єкт» визначає загальний для «Реального Суб'єкта» і «Заступника» інтерфейс, так, що «Заступник» може бути використаний скрізь, де очікується «Реальний Суб'єкт».
«Заступник» може мати і інші обов'язки, а саме:
- віддалений «Заступник» може відповідати за кодування запиту і його аргументів і відправку закодованого запиту реальному «Суб'єктові»
- віртуальний «Заступник» може кешувати додаткову інформацію про реального «Суб'єкта», щоб відкласти його створення
- захищаючий «Заступник» може перевіряти, чи має клієнтський об'єкт необхідні для виконання запиту права.
Типи замісника
- Кеш проксі. Кеш проксі покращує продуктивність реального об'єкта, коли вони виконують довгі операції, а результат цих операцій рідко змінюється. Наприклад, реальний об'єкт містить метод, що рахує прості числа. При першому виклику проксі делегує операцію реальному об'єкту і зберігає результат повернення. При всіх наступних викликах, проксі повертає кешовану інформацію.
- Проксі захисту. Проксі захисту, додає рівень захисту над реальним об'єктом. Наприклад, реальний об'єкт може отримати доступ до бази даних і повернути конфіденційні дані користувачу. Проксі-захисник міг би додати методи або властивості, які дозволяють клієнтському об'єкту забезпечити відповідну аутентифікацію, перш ніж повернути дані. Він також може фільтрувати дані відповідно до прав автентифікованого користувача.
- Віддалений проксі. Віддалений проксі-сервер надає локальний об'єкт, який посилається на реальний об'єкт в іншому місці, як правило, через мережеве з'єднання. Проксі виконує необхідні дії для кодування запитів на передачу мережі і приймає результати від віддаленого ресурсу, перш ніж повертати їх клієнту. Звичайний приклад віддаленого проксі-сервера - це локальний клас, створений Visual Studio для забезпечення доступу до вебслужби.
- Розумний проксі. Розумний проксі додає додаткову функціональність реальному об'єкта. Ця функціональність часто невидима для клієнта. Наприклад, підрахунок існуючих посилань на ресурсомісткий об'єкт таким чином, що коли лічильник досягне нуля, дані об'єкта можуть бути видалені з пам'яті. Можна також використовувати розумний проксі для логування викликів користувача до реального об'єкта.
- Віртуальний проксі. Віртуальний проксі забезпечує спрощену версію складного об'єкта. Тільки тоді, коли потрібні дані реального об'єкта, лише тоді він створюється, забезпечуючи форму лінивої ініціалізації. Наприклад, провідник Windows, може відобразити файли, який видно на екрані. При отриманні списку файлів, ім'я файлу, розмір та інша легка для отримання інформація зберігатиметься в об'єктах проксі. Тільки при команді "перегляд документа", реальний об'єкт буде створено і заповнено повним вмістом файлу, оскільки вони доступні повільніше і потребують більше пам'яті.
Переваги
- віддалений замісник;
- віртуальний замісник може виконувати оптимізацію;
- захищає замісника;
- «Розумне» посилання (вказівник);
Недоліки
- Різко збільшує час відгуку
Реалізація
C++
#include <iostream> using namespace std; struct ProxyBase { virtual void f() = 0; virtual void g() = 0; virtual void h() = 0; virtual ~ProxyBase() {} }; struct Implementation1 : public ProxyBase { void f() { cout << " Implementation1.f()" << endl; } void g() { cout << " Implementation1.g()" << endl; } void h() { cout << " Implementation1.h()" << endl; } }; struct Implementation2 : public ProxyBase { void f() { cout << " Implementation2.f()" << endl; } void g() { cout << " Implementation2.g()" << endl; } void h() { cout << " Implementation2.h()" << endl; } }; class Proxy : public ProxyBase { private: ProxyBase* implementation; public: Proxy(ProxyBase* pb) { implementation = pb; } ~Proxy() { delete implementation; } void f() { implementation->f(); } void g() { implementation->g(); } void h() { implementation->h(); } }; void main() { Proxy p(new Implementation2); p.f(); p.g(); p.h(); }
C#
class MainApp { static void Main() { // Create math proxy MathProxy 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(); } } // "Subject" 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); } // "RealSubject" class Math : 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" class MathProxy : IMath { 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); } }
using System; using System.Threading; namespace Proxy { public abstract class CalculatorBase { public abstract int Calculate(); } public class NumberMultiplier : CalculatorBase { public override int Calculate() { int result = 1; for (int i = 2; i <= 5; i++) { result *= i; // імітуємо важку операцію Thread.Sleep(500); } return result; } } // Кеш проксі public class NumberMultiplierProxy : CalculatorBase { private NumberMultiplier realNumberMultiplier; private int cachedValue; public override int Calculate() { if (realNumberMultiplier == null) { realNumberMultiplier = new NumberMultiplier(); cachedValue = realNumberMultiplier.Calculate(); } return cachedValue; } } class Program { static void Main(string[] args) { CalculatorBase cb; // перевіряємо роботу реального об'єкта cb = new NumberMultiplier(); Console.WriteLine("Real object"); for (int i = 0; i < 3; i++) { Console.WriteLine(cb.Calculate()); } // перевірямо роботу проксі cb = new NumberMultiplierProxy(); Console.WriteLine("Cache proxy"); for (int i = 0; i < 3; i++) { Console.WriteLine(cb.Calculate()); } Console.ReadLine(); } } }
Посилання
- Proxy Design Pattern [ 13 жовтня 2007 у Wayback Machine.]
- Design Patterns: Elements of Reusable Object-Oriented Software [ 9 листопада 2012 у Wayback Machine.]
Література
Алан Шаллоуей, Джеймс Р. Тротт. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М. : «Вильямс», 2002. — 288 с. — .
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Shablon Proxy Zastupnik Shablon proyektuvannya Nadaye ob yekt sho kontrolyuye dostup perehoplyuyuchi vsi vikliki do nogo ProblemaNeobhidno keruvati dostupom do ob yekta tak shob stvoryuvati gromizdki ob yekti na vimogu VirishennyaStvoriti surogat gromizdkogo ob yekta Zastupnik zberigaye posilannya yake dozvolyaye zastupnikovi zvernutisya do realnogo sub yekta ob yekt klasu Zastupnik mozhe zvertatisya do ob yekta klasu Sub yekt yaksho interfejsi Realnogo Sub yekta i Sub yekta odnakovi Oskilki interfejs Realnogo Sub yekta identichnij interfejsu Sub yekta tak sho Zastupnika mozhna pidstaviti zamist Realnogo Sub yekta kontrolyuye dostup do Realnogo Sub yekta mozhe vidpovidati za stvorennya abo vidalennya Realnogo Sub yekta Sub yekt viznachaye zagalnij dlya Realnogo Sub yekta i Zastupnika interfejs tak sho Zastupnik mozhe buti vikoristanij skriz de ochikuyetsya Realnij Sub yekt Zastupnik mozhe mati i inshi obov yazki a same viddalenij Zastupnik mozhe vidpovidati za koduvannya zapitu i jogo argumentiv i vidpravku zakodovanogo zapitu realnomu Sub yektovi virtualnij Zastupnik mozhe keshuvati dodatkovu informaciyu pro realnogo Sub yekta shob vidklasti jogo stvorennya zahishayuchij Zastupnik mozhe pereviryati chi maye kliyentskij ob yekt neobhidni dlya vikonannya zapitu prava Tipi zamisnikaKesh proksi Kesh proksi pokrashuye produktivnist realnogo ob yekta koli voni vikonuyut dovgi operaciyi a rezultat cih operacij ridko zminyuyetsya Napriklad realnij ob yekt mistit metod sho rahuye prosti chisla Pri pershomu vikliku proksi deleguye operaciyu realnomu ob yektu i zberigaye rezultat povernennya Pri vsih nastupnih viklikah proksi povertaye keshovanu informaciyu Proksi zahistu Proksi zahistu dodaye riven zahistu nad realnim ob yektom Napriklad realnij ob yekt mozhe otrimati dostup do bazi danih i povernuti konfidencijni dani koristuvachu Proksi zahisnik mig bi dodati metodi abo vlastivosti yaki dozvolyayut kliyentskomu ob yektu zabezpechiti vidpovidnu autentifikaciyu persh nizh povernuti dani Vin takozh mozhe filtruvati dani vidpovidno do prav avtentifikovanogo koristuvacha Viddalenij proksi Viddalenij proksi server nadaye lokalnij ob yekt yakij posilayetsya na realnij ob yekt v inshomu misci yak pravilo cherez merezheve z yednannya Proksi vikonuye neobhidni diyi dlya koduvannya zapitiv na peredachu merezhi i prijmaye rezultati vid viddalenogo resursu persh nizh povertati yih kliyentu Zvichajnij priklad viddalenogo proksi servera ce lokalnij klas stvorenij Visual Studio dlya zabezpechennya dostupu do vebsluzhbi Rozumnij proksi Rozumnij proksi dodaye dodatkovu funkcionalnist realnomu ob yekta Cya funkcionalnist chasto nevidima dlya kliyenta Napriklad pidrahunok isnuyuchih posilan na resursomistkij ob yekt takim chinom sho koli lichilnik dosyagne nulya dani ob yekta mozhut buti vidaleni z pam yati Mozhna takozh vikoristovuvati rozumnij proksi dlya loguvannya viklikiv koristuvacha do realnogo ob yekta Virtualnij proksi Virtualnij proksi zabezpechuye sproshenu versiyu skladnogo ob yekta Tilki todi koli potribni dani realnogo ob yekta lishe todi vin stvoryuyetsya zabezpechuyuchi formu linivoyi inicializaciyi Napriklad providnik Windows mozhe vidobraziti fajli yakij vidno na ekrani Pri otrimanni spisku fajliv im ya fajlu rozmir ta insha legka dlya otrimannya informaciya zberigatimetsya v ob yektah proksi Tilki pri komandi pereglyad dokumenta realnij ob yekt bude stvoreno i zapovneno povnim vmistom fajlu oskilki voni dostupni povilnishe i potrebuyut bilshe pam yati Perevagividdalenij zamisnik virtualnij zamisnik mozhe vikonuvati optimizaciyu zahishaye zamisnika Rozumne posilannya vkazivnik NedolikiRizko zbilshuye chas vidgukuRealizaciyaC Priklad realizaciyi na movi S include lt iostream gt using namespace std struct ProxyBase virtual void f 0 virtual void g 0 virtual void h 0 virtual ProxyBase struct Implementation1 public ProxyBase void f cout lt lt Implementation1 f lt lt endl void g cout lt lt Implementation1 g lt lt endl void h cout lt lt Implementation1 h lt lt endl struct Implementation2 public ProxyBase void f cout lt lt Implementation2 f lt lt endl void g cout lt lt Implementation2 g lt lt endl void h cout lt lt Implementation2 h lt lt endl class Proxy public ProxyBase private ProxyBase implementation public Proxy ProxyBase pb implementation pb Proxy delete implementation void f implementation gt f void g implementation gt g void h implementation gt h void main Proxy p new Implementation2 p f p g p h C Priklad realizaciyi na movi S class MainApp static void Main Create math proxy MathProxy 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 Subject 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 RealSubject class Math 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 class MathProxy IMath 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 Priklad realizaciyi na movi S using System using System Threading namespace Proxy public abstract class CalculatorBase public abstract int Calculate public class NumberMultiplier CalculatorBase public override int Calculate int result 1 for int i 2 i lt 5 i result i imituyemo vazhku operaciyu Thread Sleep 500 return result Kesh proksi public class NumberMultiplierProxy CalculatorBase private NumberMultiplier realNumberMultiplier private int cachedValue public override int Calculate if realNumberMultiplier null realNumberMultiplier new NumberMultiplier cachedValue realNumberMultiplier Calculate return cachedValue class Program static void Main string args CalculatorBase cb pereviryayemo robotu realnogo ob yekta cb new NumberMultiplier Console WriteLine Real object for int i 0 i lt 3 i Console WriteLine cb Calculate pereviryamo robotu proksi cb new NumberMultiplierProxy Console WriteLine Cache proxy for int i 0 i lt 3 i Console WriteLine cb Calculate Console ReadLine PosilannyaProxy Design Pattern 13 zhovtnya 2007 u Wayback Machine Design Patterns Elements of Reusable Object Oriented Software 9 listopada 2012 u Wayback Machine LiteraturaAlan Shallouej Dzhejms R Trott Shablony proektirovaniya Novyj podhod k obektno orientirovannomu analizu i proektirovaniyu Design Patterns Explained A New Perspective on Object Oriented Design M Vilyams 2002 288 s ISBN 0 201 71594 5