設(shè)計模式解密(5)- 外觀模式(門面模式)

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

1、簡介

外觀模式提供了一個統(tǒng)一的接口,用來訪問子系統(tǒng)中的一群接口。外觀定義了一個高層接口,讓子系統(tǒng)更容易使用。

使用外觀模式時,我們創(chuàng)建了一個統(tǒng)一的類,用來包裝子系統(tǒng)中一個或多個復(fù)雜的類,客戶端可以直接通過外觀類來調(diào)用內(nèi)部子系統(tǒng)中方法,從而外觀模式讓客戶和子系統(tǒng)之間避免了緊耦合。

外觀模式的目的不是為了給子系統(tǒng)添加新的功能接口,而是為了讓外部減少與子系統(tǒng)內(nèi)多個模塊的交互,松散耦合,從而讓外部能夠更簡單地使用子系統(tǒng)。

外觀模式的本質(zhì)是:封裝交互,簡化調(diào)用。

英文:Facade

類型:結(jié)構(gòu)型模式

 

2、實例引入

背景:模仿安裝智能家居前后的對比

操作燈光接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.designpattern.facade;
/**
* 類說明 :燈光接口
*/
public interface LightI {
    /**
     * 開燈
     */
    public void on();
    /**
     * 關(guān)燈
     */
    public void off();
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.designpattern.facade.impl;
 
import com.designpattern.facade.LightI;
 
/**
* 類說明 :燈光接口實現(xiàn)類
*/
public class Light implements LightI {
    @Override
    public void on() {
        System.out.println("打開燈");
    }
 
    @Override
    public void off() {
        System.out.println("關(guān)閉燈");
    }
}

操作電視接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.designpattern.facade;
/**
* 類說明 :電視接口
*/
public interface TVI {
    /**
     * 開機(jī)
     */
    public void on();
    /**
     * 關(guān)機(jī)
     */
    public void off();
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.designpattern.facade.impl;
 
import com.designpattern.facade.TVI;
 
/**
* 類說明 :電視接口實現(xiàn)類
*/
public class TV implements TVI {
    @Override
    public void on() {
        System.out.println("打開電視");
    }
    @Override
    public void off() {
        System.out.println("關(guān)閉電視");
    }
}

在安裝智能家居前:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.designpattern.facade;
 
import com.designpattern.facade.impl.Light;
import com.designpattern.facade.impl.TV;
 
/**
* 類說明 :測試
*/
public class Test {
    public static void main(String[] args) {
        //----晚上下班回到家----
        //開燈光
        LightI light = new Light();
        light.on();
        //看電視
        TVI tv = new TV();
        tv.on();
        //-----睡覺-----
        //關(guān)燈光
        light.off();
        //關(guān)電視
        tv.off();
    }
}

結(jié)果:

1
2
3
4
打開燈
打開電視
關(guān)閉燈
關(guān)閉電視

我們需要一個一個把需要開的電器打開,是不是好麻煩?

下面咱們引入智能家居

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.designpattern.facade;
/**
* 類說明 :智能家居總開關(guān)接口
*/
public interface SmartHomeI {
    /**
     * 總開
     */
    public void on();
    /**
     * 總關(guān)
     */
    public void off();
}

  

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
package com.designpattern.facade.impl;
 
import com.designpattern.facade.LightI;
import com.designpattern.facade.SmartHomeI;
import com.designpattern.facade.TVI;
 
/**
* 類說明 :智能家居總開關(guān)接口
*/
public class SmartHome implements SmartHomeI {
     
    private LightI light = new Light();
    private TVI tv = new TV();
     
    @Override
    public void on() {
        light.on();
        tv.on();
    }
    @Override
    public void off() {
        light.off();
        tv.off();
    }
}

安裝智能家居以后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.designpattern.facade;
 
import com.designpattern.facade.impl.Light;
import com.designpattern.facade.impl.SmartHome;
import com.designpattern.facade.impl.TV;
 
/**
* 類說明 :測試
*/
public class Test {
    public static void main(String[] args) {
        SmartHomeI smarthome = new SmartHome();
        //----晚上下班回到家----
        smarthome.on();
        //-----睡覺-----
        smarthome.off();
    }
}

結(jié)果:

1
2
3
4
打開燈
打開電視
關(guān)閉燈
關(guān)閉電視

就一個開關(guān)是不是很方便?

 

3、解決的問題

從上面的例子看:

外觀模式對客戶屏蔽了子系統(tǒng)組件,從而簡化了接口,減少了客戶處理的對象數(shù)目并使子系統(tǒng)的使用更加簡單。

外觀模式實現(xiàn)了子系統(tǒng)與客戶之間的松耦合關(guān)系,而子系統(tǒng)內(nèi)部的功能組件是緊耦合的,松耦合使得子系統(tǒng)的組件變化不會影響到它的客戶。(比如將來我換一臺電視,只需要修改一下電視接口即可,對外部的智能家居接口不需要修改,從而不影響外部使用者)

 

4、應(yīng)用場景

需要將設(shè)計進(jìn)行分層時考慮外觀模式;(在層次化結(jié)構(gòu)中,可以使用外觀模式定義系統(tǒng)中每一層的入口,其中三層架構(gòu)就是這樣的一個例子)

在開發(fā)階段,子系統(tǒng)往往因為重構(gòu)變得越來越復(fù)雜,增加外觀模式可以提供一個簡單的接口,減少它們之間的依賴;(外一個復(fù)雜的子系統(tǒng)提供一個簡單的接口)

在維護(hù)一個遺留的大型系統(tǒng)時,可以這個系統(tǒng)已經(jīng)非常難以維護(hù)和擴(kuò)展,可以為新系統(tǒng)開發(fā)一個外觀類,來提供設(shè)計粗糙或高度復(fù)雜的遺留代碼的比較清晰簡單的接口,讓新系統(tǒng)與外觀類交互,外觀模式與遺留代碼交互所有復(fù)雜的工作;(提供子系統(tǒng)的獨立性)

 

5、優(yōu)缺點

優(yōu)點:

外觀模式降低了客戶端對子系統(tǒng)使用的復(fù)雜性;

外觀模式松散了客戶端與子系統(tǒng)的耦合關(guān)系,讓子系統(tǒng)內(nèi)部的模塊能更容易擴(kuò)展和維護(hù);

通過合理使用外觀模式,可以幫助我們更好的劃分訪問的層次;

使用外觀模式還有一個附帶的好處,就是能夠有選擇性地暴露方法。一個模塊中定義的方法可以分成兩部分,一部分是給子系統(tǒng)外部使用的,一部分是子系統(tǒng)內(nèi)部模塊之間相互調(diào)用時使用的。有了外觀類,那么用于子系統(tǒng)內(nèi)部模塊之間相互調(diào)用的方法就不用暴露給子系統(tǒng)外部了;

缺點:

如果增加新的子系統(tǒng)可能需要修改外觀類或客戶端的源代碼,這樣就違背了”開——閉原則“(不過這點也是不可避免);

 

6、與其他模式對比

外觀模式與適配器模式非常類似;

外觀模式與適配器模式不同的是:適配器模式是將一個對象包裝起來以改變其接口,而外觀是將一群對象 ”包裝“起來以簡化其接口。它們的意圖是不一樣的,適配器是將接口轉(zhuǎn)換為不同接口,而外觀模式是提供一個統(tǒng)一的接口來簡化接口;

外觀模式旨在:子系統(tǒng)的高層接口;

適配器模式旨在:對象接口的變化;


7、總結(jié)

外觀模式,為子系統(tǒng)的一組接口提供一個統(tǒng)一的接口,該模式定義了一個高層接口,這一個高層接口使的子系統(tǒng)更加容易使用。并且外觀模式可以解決層結(jié)構(gòu)分離、降低系統(tǒng)耦合度和為新舊系統(tǒng)交互提供接口功能。

 

 

PS:源碼地址   https://github.com/JsonShare/DesignPattern/tree/master 

     

如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力! 
如果標(biāo)題被標(biāo)記為轉(zhuǎn)載,轉(zhuǎn)載請注明原作者地址,詳見引用 
版權(quán)聲明,轉(zhuǎn)載請注明出處:http://www.cnblogs.com/JsonShare

http://www.cnblogs.com/JsonShare/p/7121383.html