天天看點

23種設計模式-9.外觀模式(Facade Pattern)

動機(Motivate):

    在軟體開發系統中,客戶程式經常會與複雜系統的内部子系統之間産生耦合,而導緻客戶程式随着子系統的變化而變化。那麼如何簡化客戶程式與子系統之間的互動接口?如何将複雜系統的内部子系統與客戶程式之間的依賴解耦?

意圖(Intent):

    為子系統中的一組接口提供一個一緻的界面,Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

                                                                         --------《設計模式》GOF

結構圖(Struct):

适用性:

    1.為一個複雜子系統提供一個簡單接口。

    2.提高子系統的獨立性。

    3.在階層化結構中,可以使用Facade模式定義系統中每一層的入口。

生活中的例子:

代碼實作:

    我們平時的開發中其實已經不知不覺的在用Façade模式,現在來考慮這樣一個抵押系統,當有一個客戶來時,有如下幾件事情需要确認:到銀行子系統查詢他是否有足夠多的存款,到信用子系統查詢他是否有良好的信用,到貸款子系統查詢他有無貸款劣迹。隻有這三個子系統都通過時才可進行抵押。我們先不考慮Façade模式,那麼客戶程式就要直接通路這些子系統,分别進行判斷。類結構圖下: 

在這個程式中,我們首先要有一個顧客類,它是一個純資料類,并無任何操作,示意代碼:

 1 //顧客類

 2 public class Customer

 3 {

 4     private string _name;

 5 

 6     public Customer(string name)

 7     {

 8         this._name = name;

 9     }

10 

11     public string Name

12     {

13         get { return _name; }

14     }

15 }

下面這三個類均是子系統類,示意代碼:

 1 //銀行子系統

 2 public class Bank

 3 {

 4     public bool HasSufficientSavings(Customer c, int amount)

 5     {

 6         Console.WriteLine("Check bank for " + c.Name);

 7         return true;

 8     }

 9 }

10 

11 //信用子系統

12 public class Credit

13 {

14     public bool HasGoodCredit(Customer c)

15     {

16         Console.WriteLine("Check credit for " + c.Name);

17         return true;

18     }

19 }

20 

21 //貸款子系統

22 public class Loan

23 {

24     public bool HasNoBadLoans(Customer c)

25     {

26         Console.WriteLine("Check loans for " + c.Name);

27         return true;

28     }

29 }

看客戶程式的調用:

 1 //客戶程式

 2 public class MainApp

 3 {

 4     private const int _amount = 12000;

 5 

 6     public static void Main()

 7     {

 8         Bank bank = new Bank();

 9         Loan loan = new Loan();

10         Credit credit = new Credit();

11 

12         Customer customer = new Customer("Ann McKinsey");

13 

14         bool eligible = true;

15 

16         if (!bank.HasSufficientSavings(customer, _amount))

17         {

18             eligible = false;

19         }

20         else if (!loan.HasNoBadLoans(customer))

21         {

22             eligible = false;

23         }

24         else if (!credit.HasGoodCredit(customer))

25         {

26             eligible = false;

27         }

28 

29         Console.WriteLine("\n" + customer.Name + " has been " + (eligible ? "Approved" : "Rejected"));

30         Console.ReadLine();

31     }

32 }

可以看到,在不用Façade模式的情況下,客戶程式與三個子系統都發生了耦合,這種耦合使得客戶程式依賴于子系統,當子系統化時,客戶程式也将面臨很多變化的挑戰。一個合情合理的設計就是為這些子系統建立一個統一的接口,這個接口簡化了客戶程式的判斷操作。看一下引入Façade模式後的類結構圖:

           變

外觀類Mortage的實作如下:

 1 /外觀類

 2 public class Mortgage

 3 {

 4     private Bank bank = new Bank();

 5     private Loan loan = new Loan();

 6     private Credit credit = new Credit();

 7 

 8     public bool IsEligible(Customer cust, int amount)

 9     {

10         Console.WriteLine("{0} applies for {1:C} loan\n",

11           cust.Name, amount);

12 

13         bool eligible = true;

14 

15         if (!bank.HasSufficientSavings(cust, amount))

16         {

17             eligible = false;

18         }

19         else if (!loan.HasNoBadLoans(cust))

20         {

21             eligible = false;

22         }

23         else if (!credit.HasGoodCredit(cust))

24         {

25             eligible = false;

26         }

27 

28         return eligible;

29     }

30 }

顧客類和子系統類的實作仍然如下:

 1 //銀行子系統

 2 public class Bank

 3 {

 4     public bool HasSufficientSavings(Customer c, int amount)

 5     {

 6         Console.WriteLine("Check bank for " + c.Name);

 7         return true;

 8     }

 9 }

10 

11 //信用證子系統

12 public class Credit

13 {

14     public bool HasGoodCredit(Customer c)

15     {

16         Console.WriteLine("Check credit for " + c.Name);

17         return true;

18     }

19 }

20 

21 //貸款子系統

22 public class Loan

23 {

24     public bool HasNoBadLoans(Customer c)

25     {

26         Console.WriteLine("Check loans for " + c.Name);

27         return true;

28     }

29 }

30 

31 //顧客類

32 public class Customer

33 {

34     private string name;

35 

36     public Customer(string name)

37     {

38         this.name = name;

39     }

40 

41     public string Name

42     {

43         get { return name; }

44     }

45 }

而此時客戶程式的實作:

 1 //客戶程式類

 2 public class MainApp

 3 {

 4     public static void Main()

 5     {

 6         //外觀

 7         Mortgage mortgage = new Mortgage();

 8 

 9         Customer customer = new Customer("Ann McKinsey");

10         bool eligable = mortgage.IsEligible(customer, 125000);

11 

12         Console.WriteLine("\n" + customer.Name +

13             " has been " + (eligable ? "Approved" : "Rejected")); 

14         Console.ReadLine();

15     }

16 }

可以看到引入Façade模式後,客戶程式隻與Mortgage發生依賴,也就是Mortgage屏蔽了子系統之間的複雜的操作,達到了解耦内部子系統與客戶程式之間的依賴。