Home [閱讀筆記][Design Pattern] Ch12.外觀模式(Facade)
Post
Cancel

[閱讀筆記][Design Pattern] Ch12.外觀模式(Facade)

外觀模式(Facade)

「外觀模式(Facade)」又叫「門面模式」。

即使沒有聽過「外觀模式」,也很有可能常常用,因為它完美地體現了「依賴倒轉原則」和「迪米特法則」的思想

外觀模式(Facade)結構

  • Fancade外觀類別:知道哪些子系統類負責處理請求,將客戶的請求代理給適當的子系統物件。
  • SubSystem Classes子系統類別集合:實現子系統的功能,處理Fancade物件指派的任務。

注意:子類別中沒有Fancade的任何資訊,就沒有對Fancade物件的引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Client

    Fancade 外觀類別:知道哪些子系統類負責處理請求,將客戶的請求代理給適當的子系統物件
    + MethodA()
    + MethodB()

SubSystem Classes

    SubSystem1
    + MethodOne()
    SubSystem2
    + MethodOne()
    SubSystem3
    + MethodOne()
    SubSystem4
    + MethodOne()

四個子系統的類別

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class SubSystem1 {
    public void MethodOne() { 
        Console.WriteLine("子系統1的方法");
    }
}
class SubSystem2 {
    public void MethodOne() { 
        Console.WriteLine("子系統2的方法");
    }
}
class SubSystem3 {
    public void MethodOne() { 
        Console.WriteLine("子系統3的方法");
    }
}
class SubSystem4 {
    public void MethodOne() { 
        Console.WriteLine("子系統4的方法");
    }
}

外觀類別

外觀類別,它需要瞭解所有的子系統的方法或屬性,進行組合,以備外界調用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Facade {
    SubSystem1 s1;
    SubSystem2 s2;
    SubSystem3 s3;
    SubSystem4 s4;

    public Facade() {
        s1 = new SubSystem1();
        s2 = new SubSystem2();
        s3 = new SubSystem3();
        s4 = new SubSystem4();
    }

    public void MethodA() {
        s1.MethodOne();
        s3.MethodOne();
        s4.MethodOne();
        Console.WriteLine("方法組合A()");
    }
    public void MethodB() {
        s2.MethodOne();
        s3.MethodOne();
        Console.WriteLine("方法組合B()");
    }
}

用戶端調用

由於 Facade的作用,用戶端可以根本不知三個子系統類別的存在。

1
2
3
Facade facade = new Facade();
facade.MethodA();
facade.MethodB();

何時用外觀模式?

「外觀模式」在什麼時候使用最好?

這要分三個階段來說:

  1. 首先,在設計初期階段,應該要有意識的將不同的兩個層分離,比如經典的三層架構,就需要考慮在資料存取層和業務邏輯層,業務邏輯層和表示層的層與層之間建立外觀Facade,這樣可以為複雜的子系統提供一個簡單的介面,使得耦合大大降低。
  2. 其次,在開發階段,子系統往往因為不斷的重構演化而變得越來越複雜,大多數的模式使用時也都會產生很多很小的類別,這原本是好事,但也給外部調用它們的用戶程式帶來了使用上的困難,增加外觀Facade可以提供一個簡單的介面,減少它們之間的依賴。
  3. 第三,在維護一個遺留的大型系統時,可以這個系統已經非常難以維護和擴展了,但因為它包含非常重要的功能,新的需求開發必須要依賴於它。此時用外觀模式Facade也是非常適合的。你可以為新系統開發一個外觀Facade類別,來提供設計粗糙或高度複雜的遺留程式碼的比較清晰簡單的介面,讓新系統與Facade物件互動,Facade與遺留程式碼互動所有複雜的工作。

對於複雜難以維護的老系統,直接去改或去擴展都可能產生很多問題,可以分兩小組:

  • 一個開發Facade與老系統的互動
  • 另一個只要瞭解Facade的介面,直接開發新系統調用這些介面即可
    可以減少很多不必要的麻煩。

股民炒股程式碼

結構

1
2
3
4
5
6
客戶
    股票一
    股票二
    股票三
    公債一
    房地產一

程式碼

具體股票、公債、房地產

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//股票1
class Stock1 {
    //賣股票
    public void Sell() {
        Consloe.WriteLine("股票1 賣出");
    }
    //買股票
    public void Buy() {
        Consloe.WriteLine("股票1 買入");
    }
}
//股票2
class Stock2 {
    //似股票1…略
}
//股票3
class Stock3 {
    //似股票1…略
}
//公債1
class NationalDebt1 {
    //似股票1…略
}
//房地產1
class Realty1 {
    //似股票1…略
}

用戶端調用

用戶需要瞭解股票、公債、房地產情況,需要參與這些項目具體買和賣。耦合性很高。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//用戶端調用
Stock1 s1 = new Stock1();
Stock2 s2 = new Stock2();
Stock3 s3 = new Stock3();
NationalDebt1 nd1 = new NationalDebt1();
Realty1 r1 = new Realty1();

s1.Buy();
s2.Buy();
s3.Buy();
nd1.Buy();
r1.Buy();

s1.Sell();
s2.Sell();
s3.Sell();
nd1.Sell();
r1.Sell();

投資基金程式碼

結構

1
2
3
4
5
6
7
客戶
    基金
        股票一
        股票二
        股票三
        公債一
        房地產一

基金類別

基金類別,它需要瞭解所有的股票或其他投資方式的方法或屬性,進行組合,以備外界調用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Fund {
    Stock1 s1;
    Stock2 s2;
    Stock3 s3;
    NationalDebt1 nd1;
    Realty1 r1;

    public Fund() {
        //基金類別,它需要瞭解所有的股票或其他投資方式的方法或屬性,進行組合,以備外界調用
        s1 = new Stock1();
        s2 = new Stock2();
        s3 = new Stock3();
        nd1 = new NationalDebt1();
        r1 = new Realty1();
    }

    public void BuyFond() {
        s1.Buy();
        s2.Buy();
        s3.Buy();
        nd1.Buy();
        r1.Buy();
    }

    public void SellFund() {
        s1.Sell();
        s2.Sell();
        s3.Sell();
        nd1.Sell();
        r1.Sell();
    }
}

用戶端調用

此時用戶不需要瞭解股票,甚至可以對股票一無所知,買了基金就回家睡覺,一段時間後再贖回就可以大把數錢。

參與股票的操作行為都由基金公司完成。用戶端程式碼非常簡捷明瞭。

1
2
3
Fund fund = new Fund();
fund.BuyFond(); //基金購買
fund.SellFund(); //基金贖回
This post is licensed under CC BY 4.0 by the author.

[閱讀筆記][Design Pattern] Ch11.迪米特法則(LoD)

[閱讀筆記][Design Pattern] Ch13.建造者模式(Builder)