سلام امیدوارم که حالتون خوب باشه و از مسیری که توش قرار دارید لذت ببرید.
امروز قراره در مورد Proxy Design Pattern که یک الگوی طراحی ساختاری (structural) هست صحبت کنیم.
متاسفانه واژه پراکسی برای ما ایرانیا انقدر آشنا هست که همه ما با تمام سلول هامون درکش کردیم :)
البته مفهموم پراکسی در Proxy Server و Proxy Design Pattern دو موضوع متفاوت هستن ولی هر دو شون یک ایده مشترک رو بیان میکنند.
خب اول یه سوال خیلی ساده رو جواب بدیم :
تو پراکسی هایی که همه ما مجبور به استفاده ازشون هستیم دقیقا چه اتفاقی داره میفته ؟
پراکسی در واقع یک واسطه ست که به جای ما عمل میکنه. مثلا به جای اینکه ما مستقیم به سرورهای تلگرام درخواست بدیم، به Proxy Server درخواست میدیم که اون نتیجه درخواست رو به ما برگردونه. ( میدونیم که لوکیشن پراکسی سرور ها در ایران نیست و در نتیجه تلگرام اونجا فیلتر نیست پس میتونن واسطه بین ما و تلگرام باشند).
در مورد الگوی Proxy هم تقریبا همین اتفاق میفته .
پراکسی یک جایگزین یا نگهدارنده (place holder) برای یک شی دیگه ست تا ما بتونیم دسترسی به اون شی رو، کنترل و مدیریت کنیم.
پس در تعریف این الگو هم پراکسی در واقع یک کلاس واسطه ست که قراره به جای کلاس اصلی (subject) فراخوانی بشه و نماینده ای از اون باشه .
در واقع هدف اصلی الگوی Proxy ایجاد یک سطح واسطهگر بین کد کلاینت و شی مورد نظر ماست .
حالا هدف از انجا این کار چیه ؟
هدف اینه که قبل از اینکه درخواستها (منظور از درخواست اینجا فراخوانی متد های شی مورد نظر هست) به شی برسند توی لایه پراکسی قابل رصد و پردازش باشند. در این صورت میتونیم کنترل و مدیریت بهتری روی درخواست ها داشته باشیم یا حتی ویژگی های جدیدی به اون درخواست اضافه کنیم. بدون اینکه مجبور باشیم به کلاس اصلی دست بزنیم.
خب اگر آماده هستید بریم سراغ یک مثال واقعی :
قراره که برای فایل های سیستم بتونیم یه سری عملیات خوندن و نوشتن داشته باشیم. کلاس زیر رو در نظر بگیرید :
فرض کنیم بعد از یه مدت که با این کلاس کار کردیم و بدون مشکل هم همه چیز اجرا میشده حالا از ما خواسته شده که فقط افراد خاصی بتونند فایل ها رو بخونند و همچنین بعد از عملیات های مختلف لاگ هم ثبت بشه و همچنین قابلیت کش شدن هم اضافه بشه!
آیا شما تو این حالت وارد کلاس FileSystem میشید و با حرکات مختلف سامورایی کلاس اصلی رو قلع و قمع میکنید ؟
اساسا ویژگی های جدیدی که از ما خواسته شده وظیفه کلاس FileSystem نیست (اصل یک سالید)
این ویژگی های جدیدی که مطرح شده همون مدیریت و کنترل هایی هستند که قبل از درخواست به شی اصلی باید هندل بشوند (همون نیازی که پراکسی برطرف می کرد)
پس راهکار استفاده از دیزاین پترن پروکسی هست :
همونطور که تو کد بالا مشخصه بررسی کردن سطح دسترسی ها، لاگ گیری و کش کردن همگی تو لایه پراکسی داره مدیریت میشه ?
$proxy = new FileSystemProxy(new FileSystem()); $handle = $proxy->openFile('example.txt'); $data = $proxy->readFile($handle);
الگوی پراکسی در چند حالت میتونه راهکار مناسبی ارائه بده :
در صورتی که شی مورد نظر ما در یک سرویس خارجی (مثلا API خاص در یک سرور دیگه) وجود داره و ما نمیخوایم درگیر جزئیات این ارتباط بین برنامه خودمون (local) و سرور بشیم. چالش مدیریت و کنترل ارتباط بین لوکال و سرور میتونه در پراکسی هندل بشه .
فرض کنیم برای گرفتن اطلاعات مختلف از یک شی باید سطح دسترسی های خاصی هم بررسی بشه در این صورت لایه پراکسی ما میتونه این وظیفه رو به عهده داشته باشه چون قطعا وظیفه اون شی قطعا این نیست که با یه سری شرط و شروط این دسترسی ها رو چک بکنه . بنابراین اینجا پراکسی نقشی از نگهبان رو ایفا میکنه. شبیه مثال فایل سیستم که در بالا مطرح شد.
فرض کنیم کلاسی داریم که موقع ساخته شدن (در متد سازنده خودش) هزینه زیادی رو به ما تحمیل میکنه (از نظر منابع یا زمان) ، از طرفی ممکنه ما ما در اون لحظه نیازی به ساخته شدن شی به صورت کامل نداشته باشیم. بنابراین خوبه که یه پراکسی این ساخته نشدن در لحظه ای که نیاز نداریم (Lazy initialization) رو برای ما مدیریت کنه.
در این نوع پراکسی ما میتونیم ویژگی های جدید به ابجکت اضافه کنیم به عنوان مثال کش کردن یا لاگ گرفتن از ابجکت در فراخوانی های مختلف . یا حتی اینکه اگر کسی از اون ابجکت دیگه استفاده ای نمیکنه به صورت خودکار از حافظه پاک بشه. در واقع رفتار های رو وارد کلاس کردیم که شی مون هوشمندانه تر عمل کنه. و این عملکرد هم داره در سطح پراکسی مدیریت میشه.
امیدوارم مطالبی که مطرح شد براتون مفید بوده باشه و ممنون از همراهی تون