動機(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屏蔽了子系統之間的複雜的操作,達到了解耦内部子系統與客戶程式之間的依賴。