الگوی Proxy

الگوی Proxy این الگو در دسته الگوهای ساختاری قرار دارد.تعریف Gof: فراهم کردن یک جایگزین یا نگهدارنده (PlaceHolder) برای یک شی دیگر برای کنترل دسترسی به آن. یا به عبارت دیگر فراهم کردن امکان برای یک کلاس ، که یک شی دیگر بتواند روی آن کنترل داشته باشد - یا استفاده از یک واسطه به منظور جلوگیری از دسترسی مستقیم به شیء اصلی و متمرکز سازی کنترل دسترسی .UML class diagram شركت كنندگان کلاس ها و اشیاء شرکت کننده در این الگو عبارتند از:کلاس Proxy (پروکسی ریاضی MathProxy) :یک مرجع را فراهم می کند که امکان دسترسی پروکسی به موضوع واقعی (RealSubject که در تصویر بالا میبینید)را فراهم می کند. پروکسی ممکن است به Subject اشاره کند، اگر رابطهای RealSubject و Subject یکسان باشند.(برای کلاس های کوچک می تواند subject و realsubject یکی باشند. هرچند توصیه نمیشود این کار را انجام دهید) - به عبارت دیگر درون خود ارجاعی به شی واقعی (Realsubject) دارد.رابط کاربری یکسان برای subject فراهم می کند تا پروکسی بتواند برای realsubject جایگزین شود. - به عبارت دیگر واسط آن درست مانند Subject است تا بتواند خود را به جای RealSubject جا بزند.دسترسی به realsubject را کنترل می کند و ممکن است مسئول ایجاد و حذف آن باشد.مسئولیت های دیگر به نوع پروکسی بستگی دارد: پروکسی های راه دور remote proxies :مسئول رمزگذاری یک درخواست و argument های آن و برای ارسال درخواست کد شده به موضوع واقعی(Real subject)در فضای آدرس متفاوت هستند. - به عبارت دیگر برای اجرای درخواست های دریافت شده ، یک درخواست شبکه‌ای به شی راه دور (شی واقعی - RealSubject) با فراهم کردن ملزومات ویژه ی این مبادله (امنیت ، تصدیق هویت ، رمزنگاری ،فشرده سازی و غیره )ایجاد می کنند. پروکسی های مجازی virtual proxies :ممکن است اطلاعات اضافی در مورد موضوع واقعی (RealSubject) پنهان شود به طوری که آنها می توانند دسترسی به آن را به تعویق اندازند - به عبارت دیگر به دلیل این که از ابتدا شی را ایجاد نمی کند ممکن است در وهله اول اطلاعاتی نامعتبر راجع به آن فراهم کنند تا کار برنامه نویس به طور موقت راه بیفتد( مانند خصوصیّت Extent در کلاسImageProxy) پروکسی حفاظت/پروکسی تصدیق هویت protection proxies : بررسی می کند که آیا صدا زننده (Caller)دارای مجوزهای دسترسی مورد نیاز برای انجام درخواست است. - به عبارت دیگر بررسی می کند آیا کاربر جاری برای درخواستی که صادر کرده اجازه دسترسی دارد یا خیر.موضوع Subject (واسط IMath) :رابط کاربری مشترک برای RealSubject و Proxy را تعریف می کند تا پروکسی بتواند هر جایی که RealSubject انتظار می رود استفاده شود. - به عبارت دیگر واسطی است که ساختار کلاس اصلی را تعریف می کند. از طریق او است که برنامه می‌تواند به واسطه ی پراکسی با شی پنهان شده کار کند. موضوع واقعی RealSubject (کلاس ریاضی Math) :تعریف شئ واقعی که پروکسی به آن اشاره دارد. - به عبارت دیگر خودش اصلی است که قرار است مورد استفاده قرار بگیرد .ساختار کلی این الگو این کد ساختاری الگوی پروکسی را نشان می دهد که یک شیء نمایشی (پروکسی) را فراهم می کند که دسترسی به یک شی مشابه را کنترل می کند. public abstract class Subject { public abstract void Request(); } public class RealSubject: Subject { public override void Request() { Console.WriteLine("RealSubject.Request()"); } } public class SubjectProxy: Subject { private RealSubject realSubject; public override void Request() { // lazy initialization if (realSubject == null) { realSubject = new RealSubject(); } realSubject.Request(); } } public class Client { public static void UseSubject(Subject subject) { subject.Request(); } public static void Main() { Subject proxy = new SubjectProxy(); UseSubject(proxy); Console.ReadKey(); } } /* OUTPUT:RealSubject.Request()*/کد در دنیای واقعیاین کد دنیای واقعی الگوی پروکسی را برای یک شی ریاضی که توسط یک شی MathProxy نمایان می شود، نشان می دهد.using System; namespace DoFactory.GangOfFour.Proxy.RealWorld { /// <summary> /// MainApp startup class for Real-World /// Proxy Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main() { // Create math proxy MathProxy proxy = new MathProxy(); // Do the math Console.WriteLine("4 + 2 = " + proxy.Add(4, 2)); Console.WriteLine("4 - 2 = " + proxy.Sub(4, 2)); Console.WriteLine("4 * 2 = " + proxy.Mul(4, 2)); Console.WriteLine("4 / 2 = " + proxy.Div(4, 2)); // Wait for user Console.ReadKey(); } } /// <summary> /// The 'Subject interface /// </summary> 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> /// The 'RealSubject' class /// </summary> 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; } } /// <summary> /// The 'Proxy Object' class /// </summary> class MathProxy : IMath { private Math _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); } } } Output4 + 2 = 64 - 2 = 24 * 2 = 84 / 2 = 2 منبع