تصور کنید دارید روی پروژهای کار میکنید که با کلی کد پیچیده و کلاسهای مختلف سروکار دارید. هر بار که میخواهید تغییر کوچکی بدهید، باید با کلی جزئیات فنی سروکله بزنید. حتی ممکن است نگران باشید که اشتباهی در بخشی از کد باعث شود کل سیستم از کار بیفتد. آشنا به نظر میآید، نه؟
الگوی طراحی Facade در این شرایط مطرح میشود. این الگو به شما کمک میکند تا این پیچیدگیها را پشت یک دیوار ساده پنهان کنید و فقط با چیزهایی کار کنید که لازم دارید. Facade مثل یک واسطه عمل میکند که با وجود پیچیدگیهای پشت صحنه، کار را برای شما راحتتر و سرراستتر میکند.
هدف این نوشته این است که این الگو را به زبان ساده معرفی کنیم، بفهمیم کجا میتوانیم از آن استفاده کنیم، و ببینیم چرا ممکن است برای پروژههای پیچیدهی نرمافزاری ایدهآل باشد.
الگوی طراحی Facade بخشی از مجموعه الگوهای طراحی است که در کتاب معروف "Design Patterns: Elements of Reusable Object-Oriented Software" معرفی شد.

این کتاب که توسط چهار نویسنده، معروف به Gang of Four (GoF)، در سال 1994 منتشر شد، اولین مرجع رسمی برای دستهبندی و توصیف الگوهای طراحی بود.
بنابر گفته GoF هدف از الگوی Facade عبارت است از:
تهیه یک واسط يكپارچه برای مجموعهای از واسطها در یک زیرسیستم. Facade، با تعریف یک واسط سطح بالاتر، استفاده از زیرسیستم را سـادهتـر مـیكنـد.
این الگوی طراحی دقیقاً از تعاملات روزمره انسانها الهام گرفته است. وقتی به یک رستوران میروید، لازم نیست بدانید آشپزخانه چطور کار میکند، مواد غذایی از کجا میآیند، یا دستگاههای پختوپز چطور عمل میکنند. فقط با یک پیشخدمت در ارتباط هستید که سفارشتان را میگیرد و غذا را برایتان میآورد. این مفهوم ساده از زندگی به دنیای نرمافزار منتقل شده است.
حتی در جنگها، ایده Facade به نوعی استفاده شده است. در ارتشها، فرماندهان معمولاً اطلاعات را به صورت خلاصه و ساده به سربازان منتقل میکنند، نه جزئیات پیچیده استراتژیها. این کار باعث میشود وظایف به درستی اجرا شود بدون اینکه کل ساختار در معرض دید قرار گیرد.
به عنوان مثال تصور کنید شما به عنوان مدیر پروژه برای یک پروژه نسبتا بزرگ انتخاب شدهاید. در حالت اول شما خودتان وظیفه دارید مسئولیت تک تک افراد پروژه را به آنها بگویید و وظایف واگذار شده به آنها را تحویل بگیرید. در این حالت شما وظیفه دارید با تک تک افراد ارتباط برقرار کنید و همچنین برای بازخواست وظایف، شما باید نحوه ارتباط این افراد را با یکدیگر بدانید.
در حالت دوم یک نفر به عنوان سرگروه انتخاب میشود و شما مسئولیتهای واگذار شده را به او اعلام میکنید و برای تحویل وظایف فقط با او ارتباط برقرار میکنید. با مقایسه دو حالت متوجه میشویم که در حالت دوم پیچیدگی و حجم کاری شما کمتر است. در واقع در حالت دوم از الگوی Facade استفاده کردهاید. سرگروه در این حالت به عنوان کلاس Facade است.
واژه "Facade" برای اولین بار در زبان انگلیسی در قرن 17 میلادی از کلمه فرانسوی "façade" به معنی "صورت" یا "چهره" وارد شد. این انتخاب نشان میدهد که این الگو به جای نمایش تمام جزئیات، فقط "صورت" سادهای از سیستم را به نمایش میگذارد.
اسم Facade را از معماری ساختمانها وام گرفتهاند. چرا؟ زیرا وقتی مقابل یک ساختمان شیک میایستید، تنها نمای زیبا و مرتب آن را مشاهده میکنید. اما از آنچه در زیرزمین میگذرد، بیخبر میمانید؛ اینکه لولهکشیها تا چه حد پیچیده طراحی شدهاند، سیمکشیها چگونه تنظیم شدهاند، یا کارگرانی که چطور تلاش کردهاند تا این بنا شکل بگیرد. تنها چیزی که در نگاه اول به چشم میآید، همان ظاهر جذاب و منظم است، نه جزئیات پشت پرده.

همین مفهوم را به دنیای برنامهنویسی وارد کردهاند. Facade Pattern دقیقاً همان نمای شیک و مرتب است. برنامهنویسان از این الگو بهره میبرند تا پیچیدگیها را پشت یک رابط ساده پنهان کنند. به زبان ساده، این الگو به کاربران میگوید: "نگران اینهمه کلاس و متد پیچیده نباشید؛ اینجا یک رابط ساده برایتان طراحی شده که کارتان را راه میاندازد." به این ترتیب، کاربر با سیستمی ساده و قابلدرک مواجه میشود، درحالیکه تمام پیچیدگیها و جزئیات همچنان پشت پرده باقی میمانند.
برای درک بهتر، کاری که Controller در پترن MVC انجام میدهد یا حتی وقتی دارید از Dependency Injection استفاده میکنید، در حقیقت از مفهومِ الگوی Facade هم استفاده میکنید.
این مفهوم را میتوان به خرید یک ماشین هم تشبیه کرد. هنگام خرید خودرو، تنها با فرمان، پدال و دنده سروکار دارید و از این طریق ماشین را هدایت میکنید. اما هیچگاه به جزئیات عملکرد موتور یا نحوه حرکت سوپاپها نمیپردازید. Facade Pattern نیز به همین شکل، پیچیدگیها را پشت نمای ساده خود پنهان میکند!
برای درک بهتر این الگو، بهتر هست با مفاهیم پایه برنامهنویسی شیءگرا مثل کلاسها و ارتباطات بین آن ها آشنا باشید. بدانید الگوهای طراحی چی هستند و چرا استفاده میشوند، و بتوانید یک رابط ساده طراحی کنید که پیچیدگی سیستم را پنهان کند.
برای اینکه الگوریتم این الگو را به سادهترین و جذابترین شکل ممکن توضیح بدهیم، مراحل زیر را در نظر بگیرید. Facade Pattern مثل یک مدیر پروژه عمل میکند که وظایف را به اعضای تیم محول میکند، اما خودش فقط با مشتری در ارتباط است. حالا این ایده را قدم به قدم بررسی کنیم:
تصور کنید سیستم شما شامل چندین کلاس است که هرکدام وظایف خاص خود را انجام میدهند. این کلاسها به هم وابستگیهایی دارند و برای انجام یک کار مشخص باید با هم هماهنگ شوند.
در مرحله بعد، یک کلاس طراحی میکنید که نقش Facade را ایفا کند. این کلاس رابطی ساده و یکپارچه به کاربر ارائه میدهد و پشت صحنه، ارتباطات پیچیده بین کلاسهای مختلف را مدیریت میکند.
در کلاس Facade، متدهایی تعریف میکنید که درخواستهای کاربر را دریافت و آنها را به کلاسهای داخلی ارسال میکند. Facade میداند که برای انجام هر وظیفه، باید کدام کلاسها را فراخوانی کند و چطور آنها را باهم ترکیب کند.
تصور کنید باید کدی بنویسید که با مجموعهای گسترده از اشیاء متعلق به یک کتابخانه یا فریمورک پیچیده کار کند. بهطور معمول، شما باید تمام آن اشیاء را مقداردهی اولیه کنید، وابستگیهایشان را مدیریت کنید، و متدها را به ترتیب درست اجرا کنید.
نتیجه این میشود که منطق کاری کلاسهایتان به جزئیات پیادهسازی کلاسهای شخص ثالث گره میخورد. این امر کد شما را نهتنها دشوار برای فهم، بلکه سخت برای نگهداری میکند.
داشتن یک Facade زمانی بسیار مفید است که بخواهید برنامه خود را با یک کتابخانه پیچیده که دارای دهها قابلیت مختلف است، ادغام کنید؛ اما شما فقط به بخش کوچکی از این قابلیتها نیاز دارید.
فرض کنید میخواهید برنامهای بنویسید که ویدیوهای کوتاه و بامزه از گربهها را در شبکههای اجتماعی آپلود کند. این برنامه ممکن است به کتابخانه حرفهای تبدیل ویدیو نیاز داشته باشد. اما واقعیت این است که تنها چیزی که نیاز دارید، کلاسی با یک متد ساده به نام encode(filename, format) است. با ایجاد چنین کلاسی و اتصال آن به کتابخانه تبدیل ویدیو، شما اولین Facade خود را ساختهاید.
در شکل زیر کلاس دیاگرام مربوط به این الگو را میبینید.

+ یک کلاس Facade اضافی میتواند ایجاد شود تا از آلوده شدن یک Facade اصلی به ویژگیهای نامرتبط جلوگیری کند. این کار باعث میشود Facade به ساختاری پیچیده و دستوپاگیر تبدیل نشود. این Facadeهای اضافی میتوانند هم توسط کاربران (Clients) و هم توسط دیگر 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 اینجا به کمک ما میاید تا این پیچیدگیها رو حذف کنیم و در نتیجه کدهای سادهتر و با قابلیت استفاده مجدد داشته باشیم!
میخواهیم ارسال 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 !
این الگو مثل یه منشی حرفهای هست که ما را از دردسر سیستمهای پیچیده نجات میدهد. به جای اینکه ما با تعداد زیادی از کلاس ها و متد ها سر و کله بزنیم، فقط با یه رابط ساده (Facade) کار میکنیم و بقیه کارها خودشان در پشت صحنه حل و فصل میشوند. مزیت آن: کار راحتتر، کد مرتبتر. ولی اگر دقت نکنید، Facade میتواند خودش یک مشکل بزرگ بشود .