درود دوستان! می‌خوایم با الگوی Facade (فِساد) آشنا بشیم که بهمون کمک می‌کنه خیلی راحت‌تر و ساده‌تر با کدهای پیچیده کار کنیم. اگه یک برنامه (کلاس، کتابخونه، ابزار) پیاده‌سازی سخت و پیچیده‌ای داره، این الگو به کارمون میاد 👋

 

توی این قسمت یاد می‌گیریم که:

 

مشکل کجاست؟ 🤔

می‌دونیم که برای درست کردن یک غذای خوب و لذیذ، با رعایت جزییات فراوان باید چندین دستورالعمل رو اجرا کنیم. گاهی اوقات ما یک غذای لذیذ می‌خوایم ولی فرصت و شرایطش رو نداریم. به رستوران می‌ریم. یک پیشخدمت آراسته به سمت ما میاد. با یک سفارش ساده، بعد از چند دقیقه غذای مورد علاقه‌مون روی میز ما قرار می‌گیره.
همونطور که می‌بینیم تنها کاری که باید انجام بدیم سفارش دادن غذا به پیشخدمت هست تا همه پیچیدگی‌های آماده‌سازی غذا محو بشه 🍕🤤

توی این داستان، پیشخدمت نقش الگوی Facade رو بازی می‌کنه و همهٔ پیچیدگی‌های درست‌کردن غذا همون جزییاتی هستن که از دید ما (کاربر) حذف میشن. پیشخدمت رابطی هست بین ما و اون پیچیدگی‌ها. ما فقط با پیشخدمت سر و کار داریم و رعایت دستورالعمل‌های آماده‌سازی غذا به عهدهٔ ما نیست. پیشخدمت (Facade) خودش می‌دونه باید چکار کنه.

یک مثال دیگه می‌تونه روشن کردن اتومبیل باشه. کافیه ما سوئیچ رو بچرخونیم تا ماشین برامون روشن بشه. ما نمی‌دونیم پشت پرده چه اتفاقاتی میوفته. سوئیچ یک رابط (Facade) هست.

 

مثال دنیای برنامه‌نویسی

تا به حال با کتابخونه یا ابزاری کار کردین که قبل استفاده از اون باید کلی مراحل پیاده‌سازی رو انجام بدین؟ فرض کنیم می‌خوایم به کاربرها SMS بدیم و برای این کار کتابخونه‌ای داریم که بهمون اجازه میده از سرویس‌دهنده‌های مختلفی استفاده کنیم. کدهایی که این کتابخونه برای ارسال پیام بهمون ارائه میدن به این صورت هست:

class SmsLibrary {
  constructor(client_id, client_secret, driver) {
    // ...
  }

  public recipient(phone_number) {
    // ...
  }

  public send(text) {
    // send
  }
}

که برای استفاده از اون باید چنین کدی بنویسیم:

const client_id     = config('sms.client_id');
const client_secret = config('sms.client_secret');
const sms_driver    = config('sms.driver');

const sms = new SmsLibrary(client_id, client_secret, sms_driver);

sms.recipient('+989...');
sms.send('Welcome. Our app is great!');

همونطور که می‌بینیم برای ارسال پیام باید کتابخونه رو به این صورت پیاده‌سازی کنیم. کار زمانی سخت میشه که می‌خوایم توی چندین قسمت دیگهٔ از برنامه چنین کاری انجام بدیم. الگوی Facade اینجا به کارمون میاد تا این پیچیدگی‌ها رو حذف کنیم و در نتیجه کدهای ساده‌تر و با قابلیت استفاده مجدد داشته باشیم 👌

 

الگوی Facade چیه؟

الگوی Facade با ارائه دادن یک رابط ساده، همهٔ پیچیدگی‌های کار با یک کد، کلاس، کتابخونه و ... رو برای کاربر مخفی می‌کنه.

این الگو زیر مجموعه الگوهای Structural - الگوهایی که کمک می‌کنن تا آبجکت‌های موجود طوری با هم در تعامل باشن تا بتونیم ساختارهای بزرگتری طراحی کنیم - هست و پیاده‌سازی خیلی راحتی داره.

 

پیاده‌سازی الگوی Facade

می‌خوایم مثال ارسال SMS رو با این الگو بنویسم. برای این کار ابتدا یک کلاس می‌سازیم. این کلاس، همون کلاس Facade ما هست که توی اون جزییات پیاده‌سازی کتابخونه رو می‌نویسیم:

class SmsFacade {
  public <<static>> send(text, recipient) {
    const client_id     = config('sms.client_id');
    const client_secret = config('sms.client_secret');
    const sms_driver    = config('sms.driver');
    
    const sms = new SmsLibrary(client_id, client_secret, sms_driver);
    
    sms.recipient(recipient);
    sms.send(text);
  }
}

حالا هر جایی از برنامه که می‌خوایم پیام ارسال کنیم، کافیه این کلاس رو اضافه و به این صورت از اون استفاده کنیم:

SmsFacade.send('Welcome!', '+989...');
// ...
SmsFacade.send('Your 2FA code', '+001...');

به همین سادگی! ¯\_(ツ)_/¯

همونطور که می‌بینیم، این الگو نقش یک رابط رو بین کاربر (قسمتی که از کتابخونه استفاده می‌کنه) و کدهای اصلی کتابخونه بازی می‌کنه. این الگو فقط دستورات رو منتقل می‌کنه و خودش تاثیری توی خروجی نداره. درست مثل پیشخدمت که خودش تاثیری توی خروجی غذایی که می‌خوایم نداره و فقط دستورات منتقل می‌کنه.

همچنین اون کتابخونه پیچیدهٔ خارجی که اون رو توی Facade می‌نویسیم، خودش از وجود Facade بی‌خبر هست و براش فرقی نمی‌کنه که به صورت مستقیم داره استفاده میشه و یا توسط Facade.

(Star بزنین! 👋)

 

مزایا و معایب الگوی Facade

همونطور که دیدیم وقتی جزییات پیاده‌سازی یک کد پیچیده از دیدگاه کاربر مخفی میشه، وابستگی بین اجزای برنامه هم کمتر میشه و می‌تونیم کدهایی با قابلیت استفاده مجدد داشته باشیم. برای مثال اگه بعداً بخوایم از یک کتابخونه دیگه استفاده کنیم یا تغییری توی روند پیاده‌سازی کتابخونه انجام بدیم، کافیه فقط کلاس Facade رو دست بزنیم.

از معایب استفاده از این الگوی اینه که قدرت شخصی‌سازی و استفاده از همهٔ امکانات اون کتابخونه برای کاربر پایین میاد. مثل غذایی که توی رستوران سفارش می‌دیم که اونجا کنترل خیلی کمتری روی کیفیت و جزییات غذا داریم نسبت به وقتی که خودمون به صورت مستقیم دست به کار می‌شیم.

 

خب دوستان این هم از این الگوی Facade. امیدوارم استفاده کرده باشین. روزتون خوش 😉✌️

 

https://en.wikipedia.org/wiki/Facade_pattern

https://refactoring.guru/design-patterns/facade