الگوی طراحی Facade چیست؟

تهیه‌کننده مقاله : رحیم لطفی و پویان فهیمی

5 دقیقه زمان مطالعه
1401/09/01
0 نظر

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

 اگر زیر سیستمی حاوی چند کلاس باشد و این کلاس‌ها با همدیگر همکاری کنند تا سرویس‌هایی را که قرار است زیر سیستم ارائه دهد را تداراک ببینند، ریسکی در ایجاد واسط به آن زیر سیستم وجود دارد. هر کلاس، ممکن است چندین عملیات داشته باشد؛ زیر سیستم‌های دیگر باید  توانایی ارسال پیام به نمونه‌هایی از هر کلاس را داشته باشند.

به این ترتیب، یک اتصال قوی بین زیر سیستم‌ها به وجود می‌آید و اگر تغییر در کلاس‌های یک زیر سیستم ارائه‌دهنده سرویس به‌ وجود بیاید، نیاز داریم تمام مکان‌ها در زیر سیستم‌هایی که عملیات این کلاس ها را فراخوانی کرده‌اند را ردیابی کنیم.

برای غلبه بر این وضعیت می‌توانیم از الگوی Facade استفاده کنیم؛ به این صورت که با ایجاد کلاس Facade، واسطی را به زیر سیستم اضافه کنیم. این کلاس به عنوان نماینده زیرسیستم مورد نظر با زیرسیستم‌های دیگر عمل می‌کند. بنابراین، تغییر در پیاده‌سازی کلاس‌های زیر سیستم اثر محدودی بر زیر سیستم‌های دیگر دارد.

همچنین اگر تغییری در کلاس‌ها صورت بگیرد، فقط لازم است نقاطی در زیر سیستم‌های دیگر پیدا شود که در آن‌ها، پیامی به نمونه‌های کلاس Facade ارسال شده است. بنابراین این الگو با به کارگیری مکانیسمی، دسترسی آسان کاربر به زیرسیستم‌ها را فراهم می‌کند.

گفتنی است، زیر سیستم یا همان SubSystem به مجموعه‌ای از کلاس‌ها گفته می‌شود که با هم در ارتباط هستند و برای تامین یک هدف و منظور خاص با هم کار می‌کنند [۴]. کاربر مربوط به این زیرسیستم‌ها شاید نیاز داشته باشد با تعدادی از این کلاس‌ها کار کند که ارتباط مستقیم کاربر با کلاس‌ها، همبستگی بین آن‌ها را بالا می‌برد.

زمانی‌که درون زیرسیستم تغییراتی داشته‌ باشیم، کاربر آن نیز مجبور به تغییرات می‌شود. مساله دیگر این‌که کاربر مجبور به دانستن منطق کل سیستم است که پیچیدگی خاص خود را به دنبال دارد. برای رفع این مشکل از الگوی طراحی Facade استفاده می‌کنیم؛ به این نحو که یک واسط ساده همانند یک پوسته روی کل زیرسیستم قرار می‌دهیم و هر زمان کاربر بخواهد از کلاس‌های زیرسیستم استفاده کند، از این واسط استفاده می‌کند. با این عمل وابستگی کم‌تر و مدیریت آن بیشتر می‌شود [۱۰].

به عنوان مثال تصور کنید شما به عنوان مدیر پروژه برای یک پروژه نسبتا بزرگ انتخاب شده‌اید:

  • در حالت اول شما خودتان وظیفه دارید مسئولیت تک تک افراد پروژه را به آن‌ها بگویید و وظایف واگذار شده به آن‌ها را تحویل بگیرید. در این حالت شما وظیفه دارید با تک تک افراد ارتباط برقرار کنید و همچنین برای بازخواست وظایف، شما باید نحوه ارتباط این افراد را با یکدیگر بدانید.
  • در حالت دوم یک نفر به عنوان سرگروه انتخاب می‌شود و شما مسئولیت‌های واگذار شده را به او اعلام می‌کنید و برای تحویل وظایف فقط با او ارتباط برقرار می‌کنید. با مقایسه دو حالت متوجه می‌شویم که در حالت دوم پیچیدگی و حجم کاری شما کم‌تر است. در واقع در حالت دوم از الگوی Facade استفاده کرده‌اید. سرگروه در این حالت به عنوان کلاس Facade است.

در شکل ۱، کلاس دیاگرام مربوط به این الگو نمایش داده شده و در زیر آن شرکت‌کنندگان در آن و نقش هریک بیان شده است.

بنابر گفته GoF هدف از الگوی Facade عبارت است از:

«تهیه یک واسط يكپارچه برای مجموعه‌ای از واسط‌ها در یک زیرسیستم Facade، با تعریف یک واسط سطح بالاتر، استفاده از زیرسیستم را سـاده‌تـر مـی‌كنـد.»

 Class Diagram یا نمودار کلاس:

Facade شکل ۱: کلاس دیاگرام الگوی

نقش کلاس‌ها:

  • Facade:

کلاسی که تمام زیرسیستم‌ها را می‌شناسد و می‌داند جواب درخواست کلاینت را باید از کجا بگیرد.

  • Subsystem classes:

پیاده‌سازی وظایفی که یک زیرسیستم دارد.

راه‌اندازی درخواست‌هایی که از طرف Facade صادر می‌شود.

هیچ دانشی در خصوص Facade ندارد و هیچ ارجاعی به آن ندارد.

دیگر ویژگی‌های کلیدی:

در جدول ۱، به صورت خلاصه هدف الگو، نام یا نام‌های دیگری که الگو با آن شناخته می‌شود، مواقعی که می‌توان از این الگو استفاده کرد، مزایا و معایب استفاده از این الگو و الگوهای مرتبط به این الگو توضیح داده شده است.

جدول۱ : ویژگی‌های Facade

یک مثال برای الگوی طراحی Facade:

در زیر مثالی از این الگو پیاده‌سازی شده ‌است:

مساله: قصد داریم یک برنامه کاربردی برای پرداخت وام به مشتری پیاده‌سازی کنیم که از یک زیرسیستم استفاده می‌کند تا ببیند شرایط احراز وام را دارد یا خیر [۱۶].

راه‌حل: برای پیاده‌سازی از الگوی Facade استفاده می‌کنیم.

در اینجا کلاس‌های Bank ،Credit ،Loan ، Mortgage و Customer را داریم.

Bank: موجودی بانک را برای پرداخت وام بررسی می‌کند.

Credit: اعتبارات بانک را بررسی می‌کند.

Loan: بازپرداختی وام‌های قبلی را چک می‌کند.

مجموعه این سه کلاس زیرسیستم ما را تشکیل می‌دهند.

Customer: مشخصات مشتری مورد نظر را دارد.

Mortgage: در این کلاس شرایط احراز را بررسی می‌شود؛ به این صورت که این کلاس طبق کلاس دیاگرام، نقش کلاس Facade را دارد و در آن یک متد به نام IsEligible وجود دارد که شرایط احراز را بررسی می‌کند.

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

پیاده‌سازی:


namespace Mortgage_Facade {
  class Program {
    static void Main(string[] args)  {
      Mortgage mortgage = new Mortgage();
      Customer customer = new Customer("Behnoosh");
      bool eligible = mortgage.IsEligible(customer, 50000);
      Console.WriteLine("\n" + customer.Name +" has been " + (eligible ? "Approved" :   
       "Rejected"));    	
       Console.ReadKey();  } } }


class Bank {
   public bool HasSufficientSavings(Customer c, int amount) {
      Console.WriteLine("Check bank for " + c.Name);
       return true; }  }


class Credit {
   public bool HasGoodCredit(Customer c)  {
      Console.WriteLine("Check credit for " + c.Name);
       return true;  }  }


class Loan {
  public bool HasNoBadLoans(Customer c) {
    Console.WriteLine("Check loans for " + c.Name);
    return true; } }


class Customer {
   private string _name;

   public Customer(string name) {
            this._name = name;  }

    public string Name {
            get { return _name; } } }


class Mortgage {
   private Bank _bank = new Bank();
   private Loan _loan = new Loan();
   private Credit _credit = new Credit();

   public bool IsEligible(Customer cust, int amount) {
     Console.WriteLine("{0} applies for {1} loan\n",cust.Name, amount);
     bool eligible = true;
       if (!_bank.HasSufficientSavings(cust, amount)) {
         eligible = false; }

       else if (!_loan.HasNoBadLoans(cust)) {
         eligible = false;  }
       else if (!_credit.HasGoodCredit(cust)) {
         eligible = false; }
      return eligible; } }

خروجی:

D:\voice ostad\a-prj nahayi\part\9-facad\out.png

منابع:

[۱]
Muller, Peter. Introduction to Object-Oriented Programming Using C++. Technical report, Globewide Network Academy, 1996.
[۲]
Cooper, James William. Visual Basic design patterns: VB 6.0 and VB. NET. Addison-Wesley Professional, 2002.
[۳]
Martin, Micah, and Robert C. Martin. Agile principles, patterns, and practices in C#. Pearson Education, 2006.
[۴]
Larman, Craig. Applying UML and patterns:an introduction to object-oriented analysis and design and iterative development. Pearson Education India, 2005.
[۵]
Wegner,Peter.”Concepts and paradigms of object-oriented programming.” ACM SIGPLAN OOPS Messenger 1.1 (1990): 7-87.