الگوی وکالت

UML
بندانگشتی
الگوی وکالت در برنامه‌نویسی، از جمله الگوهای طراحی نرم‌افزار می‌باشد.
وکیل، در کلی‌ترین حالت، کلاس واسطه‌ای برای انجام کار دیگری است. پروکسی می‌تواند رابط هر چیزی باشد: یک ارتباطه تحت شبکه، شیء بزرگی در داخل حافظه، یک فایل، یا یک سری از منابع دیگر که نمونه‌سازی از آن‌ها بسیار سخت یا غیرممکن است. به صورت خلاصه، وکیل پوشه‌بند یا نیروی اجرایی‌ای است که توسط مشتری صدا زده می‌شود تا به شیء اصلی در پشت‌پرده دسترسی پیدا کند. استفاده از وکیل می‌تواند انتقال به شی واقعی را راحت‌تر کند یا روش‌های دیگری برای آن بوجود بیاورد. در الگوی وکالت قابلیت‌های اضافه‌تر می‌تواند بوجود بیاید، به‌طور مثال، استفاده از حافظه موقت، برای وقتی که استفاده از شیء اصلی هزینه پردازشی و هزینه دسترسی به حافظه زیادی داشته باشد، یا در چک کردن شرایط اولیه قبل از آن که عملیات بر روی شیء اصلی اعمال شود. برای مشتری با استفاده از وکیل مانند استفاده از شیء اصلی است، چرا که رابط هر دو مشابه است.
سناریوهای احتمالی استفاده
وکالت از راه دور
در ارتباطات اشیاء توزیع شده، از یک شیء محلی به عنوان نمایش‌دهنده شیء خارجی (که متعلق به یک فضای خارجی از آدرس‌دهی‌ها است) می‌باشد. شیء محلی به عنوان وکیل شیء خارجی شناخته می‌شود، و اجرای توابع شیء محلی به اجرای توابع در شیء اصلی می‌انجامد. به عنوان مثال: دستگاه خودپرداز، که در آن یک وکیل از اطلاعات بانکی در سرور خارجی وجود دارد.
وکالت مجازی
در مواجهه به شیء پیچیده یا سنگین وزن (از نظر حافظه)، در بعضی موارد نشان دادن تنها بدنه‌ای از شیء می‌تواند مفیدتر باشد. وقتی که تصویر ایجاد شده اندازه بزرگی داشته باشد، می‌تواند توسط یک وکیل مجازی، که بر روی شیء واقعی پیاده‌سازی شده، نشان داده شود.
وکالت امنیتی
برای محافظت از کنترل دسترسی‌ها می‌توان این وظیفه را به یک وکیل سپرد.
مثال
C#
interface ICar
void DriveCar();
// Real Object
public class Car : ICar
public void DriveCar()
Console.WriteLine("Car has been driven!");
//Proxy Object
public class ProxyCar : ICar
private Driver driver;
private ICar realCar;
public ProxyCar(Driver driver)
this.driver = driver;
this.realCar = new Car();
public void DriveCar()
if (driver.Age
16)
realCar->DriveCar();
else
std::cout
DriveCar();
delete car;
car = new ProxyCar(25);
car->DriveCar();
delete car;
کریستال
abstract class AbstractCar
abstract def drive
end
class Car <AbstractCar
def drive
puts "Car has been driven!"
end
end
class Driver
getter age : Int32
def initialize(@age)
end
end
class ProxyCar <AbstractCar
private getter driver : Driver
private getter real_car : AbstractCar
def initialize(@driver)
@real_car = Car.new
end
def drive
if driver.age <= 16
puts "Sorry, the driver is too young to drive."
else
@real_car.drive
end
end
end
Program
driver = Driver.new(16)
car = ProxyCar.new(driver)
car.drive
driver = Driver.new(25)
car = ProxyCar.new(driver)
car.drive
خروجی
Sorry, the driver is too young to drive.
Car has been driven!
Delphi / Object Pascal
// Proxy Design pattern
unit DesignPattern.Proxy;
interface
type
// Car Interface
ICar = interface
procedure DriveCar;
end;
// TCar class, implementing ICar
TCar = Class(TInterfacedObject, ICar)
class function New: ICar;
procedure DriveCar;
End;
// Driver Interface
IDriver = interface
function Age: Integer;
end;
// TDriver Class, implementing IDriver
TDriver = Class(TInterfacedObject, IDriver)
private
FAge: Integer;
public
constructor Create(Age: Integer); Overload;
class function New(Age: Integer): IDriver;
function Age: Integer;
End;
// Proxy Object
TProxyCar = Class(TInterfacedObject, ICar)
private
FDriver: IDriver;
FRealCar: ICar;
public
constructor Create(Driver: IDriver); Overload;
class function New(Driver: IDriver): ICar;
procedure DriveCar;
End;
implementation
{ TCar Implementation
class function TCar.New: ICar;
begin
Result := Create;
end;
procedure TCar.DriveCar;
begin
WriteLn(Car has been driven!);
end;
{ TDriver Implementation
constructor TDriver.Create(Age: Integer);
begin
inherited Create;
FAge := Age;
end;
class function TDriver.New(Age: Integer): IDriver;
begin
Result := Create(Age);
end;
function TDriver.Age: Integer;
begin
Result := FAge;
end;
{ TProxyCar Implementation
constructor TProxyCar.Create(Driver: IDriver);
begin
inherited Create;
Self.FDriver := Driver;
Self.FRealCar := TCar.Create AS ICar;
end;
class function TProxyCar.New(Driver: IDriver): ICar;
begin
Result := Create(Driver);
end;
procedure TProxyCar.DriveCar;
begin
if (FDriver.Age <= 16)
then WriteLn(Sorry, the driver is too young to drive.)
else FRealCar.DriveCar();
end;
end.
استفاده
program Project1;
{$APPTYPE Console
uses
DesignPattern.Proxy in DesignPattern.Proxy.pas;
begin
TProxyCar.New(TDriver.New(16)).DriveCar;
TProxyCar.New(TDriver.New(25)).DriveCar;
end.
جاوا
این کد Java یک نمونه از «وکالت مجازی» را به نمایش می‌گذارد. کلاس ProxyImage برای دسترسی به کنترل از راه دور استفاده می‌شود.
مثال به جای آن که ابتدا کلاس را بسازد ابتدا یک رابط به نام displayImage ساخته است که توسط تمامی کلاس‌هایی که آن را پیاده می‌کنند نوشته می‌شود.
کلاس وکالت ProxyImage بر روی سامانه دیگری اجرا می‌شود و تصویر اصلی RealImage را در آن‌جا نمایش می‌دهد. اطلاعات تصویر از روی حافظه دسترسی پیدا می‌کنند. با استفاده از الگوی وکالت، کد ProxyImage جلوی دسترسی‌های متعدد به تصویر را می‌گیرد و دسترسی به آن از سامانه دیگر موجب بهینه سازی در استفاده از حافظه خواهد بود. لازم به ذکر است که هرچند فراخوانی کاهلانه‌ای که در این مثال نمایش داده شده جزو الگوی وکالت اصلی نیست، در حقیقت یک ویژگی پیشرفته‌تر است که توسط الگوی وکالت امکان‌پذیر شده‌است.
interface Image {
public void displayImage();
// On System A
class RealImage implements Image {
private String filename = null;
* Constructor
* @param filename
public RealImage(final String filename) {
this.filename = filename;
loadImageFromDisk();
* Loads the image from the disk
private void loadImageFromDisk() {
System.out.println("Loading " + filename);
* Displays the image
public void displayImage() {
System.out.println("Displaying " + filename);
// On System B
class ProxyImage implements Image {
private RealImage image = null;
private String filename = null;
* Constructor
* @param filename
public ProxyImage(final String filename) {
this.filename = filename;
* Displays the image
public void displayImage() {
if (image == null) {
image = new RealImage(filename);
image.displayImage();
class ProxyExample {
* Test method
public static void main(final String arguments) {
final Image image1 = new ProxyImage("HiRes_10MB_Photo1");
final Image image2 = new ProxyImage("HiRes_10MB_Photo2");
image1.displayImage(); // loading necessary
image1.displayImage(); // loading unnecessary
image2.displayImage(); // loading necessary
image2.displayImage(); // loading unnecessary
image1.displayImage(); // loading unnecessary
خروجی برنامه:
Loading HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Loading HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo1
الگوهای طراحی نرم‌افزار
الگوی دکوراتور
مقداردهی اولیه کاهلانه