Замісник (шаблон проєктування)Шаблон Proxy (Заступник) — Шаблон проєктування. Надає об'єкт, що контролює доступ, перехоплюючи всі виклики до нього. ПроблемаНеобхідно керувати доступом до об'єкта так, щоб створювати громіздкі об'єкти «на вимогу». ВирішенняСтворити сурогат громіздкого об'єкта. «Заступник» зберігає посилання, яке дозволяє заступникові звернутися до реального суб'єкта (об'єкт класу «Заступник» може звертатися до об'єкта класу «Суб'єкт», якщо інтерфейси «Реального Суб'єкта» і «Суб'єкта» однакові). Оскільки інтерфейс «Реального Суб'єкта» ідентичний інтерфейсу «Суб'єкта», так, що «Заступника» можна підставити замість «Реального Суб'єкта», контролює доступ до «Реального Суб'єкта», може відповідати за створення або видалення «Реального Суб'єкта». «Суб'єкт» визначає загальний для «Реального Суб'єкта» і «Заступника» інтерфейс, так, що «Заступник» може бути використаний скрізь, де очікується «Реальний Суб'єкт». «Заступник» може мати і інші обов'язки, а саме:
Типи замісника
Переваги
Недоліки
Реалізація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();
}
}
}
Посилання
ЛітератураАлан Шаллоуей, Джеймс Р. Тротт. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М. : «Вильямс», 2002. — 288 с. — ISBN 0-201-71594-5.
|