1. 程式人生 > >Java設計模式系列十三(外觀模式)

Java設計模式系列十三(外觀模式)

故事一

A:聽說最近出了某款遊戲超好玩,但是我電腦帶不起來,需要個組裝機玩遊戲。

B:你說XX遊戲嗎?真的很好玩,筆記本玩不了,我就是用的組裝機玩的呢。

A:是嗎?我對配置這些都不太懂,我得先去研究,然後還需要花時間從CPU、記憶體、主機板、顯示器等等這些一家家跑,再回來組裝。

B:哪需要這麼麻煩啊,你根本不用一個個去跑著買回來組裝啊,又耽誤時間又浪費精力。你不知道有專門的組裝電腦的賣家嗎?直接去找他們,把你想要的配置告訴他們就好了,其他你都不用管,他們會把組裝好的電腦直接送給你。

A:真的嗎?那你有聯絡方式嗎,給我一下,我找他們幫我組裝電腦。

過了幾天後...

A:哇、小B,太感謝你啦,我上次聯絡了組裝電腦的賣家,把我想要的配置告訴他們以後,他們當天就把組裝好的電腦給我送來了,效率太高了,我當天晚上就玩了那款超火的遊戲,還帶妹子玩的飛起,哈哈!

B:太陽,你又裝我,晚上單挑,我虐死你

故事二

A和B都是從外地到杭州打工的青年,A最近剛好搬家到了一個新小區,居住證也在一個星期後到期,需要續簽,中午吃飯的時候和B聊到這個事。

B:聽說你搬家了?

A:是啊,昨天剛搬,社群週末不上班,還沒來得及去登記呢,居住證也快到期了,還要去列印最近半年社保證明,再去派出所辦理續簽,請一上午假都不知道夠不夠?

B:我就說你平時就知道打遊戲,其他事都不關心,杭州早就實行"最多跑一趟"的服務了,早就不用一個地方一個地方去跑啦,直接去XX派出所就行啦,他們會幫你登記好,住址改簽,會幫你列印好社保證明,給你把居住證續簽。

A:真的嗎?那我只要去派出所就行了,實在太方便了,謝謝你啊!

B:可不是嘛,像什麼換駕照啊、車牌啊這些,都不用像以前那樣一個地方一個地方跑那麼麻煩了,只需要去一個地方,就能一次性把事情辦好。我說你平時真的要少玩點遊戲,如果想在杭州定居,你要對這些政策多關係一點,以後少跑點彎路。

A:嘿嘿,都被你說的有點不好意思了,難怪你小子都快結婚了,是有原因的啊,哈哈!

B:別別,你是憑實力單身,在下比不了,服!

上面兩個都是會經常發生在我們身邊的故事,我們從抽象的角度來審視一下:

  1. 故事一A作為我們的客戶端,電腦城作為我們一個龐大的主系統,cpu、主機板、記憶體這些店作為一個個系統子模組,那麼組裝電腦的店是什麼角色呢?

  2. 故事二A依然作為客戶端,人口檔案管理作為一個龐大的主系統,社群、社保局、銀行等作為一個個系統子模組,那麼只需要跑一趟的派出所是什麼角色呢?

下面,進入我們今天的主題,JAVA設計模式之——外觀模式。

什麼是外觀模式

Facade Pattern: Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

外觀模式(Facade Pattern):為子系統中的一組介面提供一個一致的介面,外觀模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。外觀模式又稱為門面模式,它是一種物件結構型模式。

通俗點說,就是通過引入一個外觀角色,來簡化客戶端與子系統之間的互動,為複雜的子系統呼叫提供一個統一的入口,降低子系統與客戶端的耦合度,且客戶端呼叫子系統更加方便。正如前言故事中的電腦組裝店和一站式服務派出所。他們就是充當了外觀角色。

外觀模式的兩個角色

  • Facade(外觀角色):在客戶端可以呼叫它的方法,在外觀角色中可以知道相關的(一個或者多個)子系統的功能和責任;在正常情況下,它將所有從客戶端發來的請求委派到相應的子系統去,傳遞給相應的子系統物件處理。

  • SubSystem(子系統角色):在軟體系統中可以有一個或者多個子系統角色,每一個子系統可以不是一個單獨的類,而是一個類的集合,它實現子系統的功能;每一個子系統都可以被客戶端直接呼叫,或者被外觀角色呼叫,它處理由外觀類傳過來的請求;子系統並不知道外觀的存在,對於子系統而言,外觀角色僅僅是另外一個客戶端而已。

外觀模式的UML圖

外觀模式程式碼例項

我們以轎車為例,以往的汽車,我們用鑰匙點火後,白天要自己開日行燈,晚上要手動開大燈,霧天手動開霧燈,冷熱也要自己開空調,還有下雨要開雨刮器等等,雖然我們都可以一個個去操作控制,但是高峰期路況太多,很多人反應不過來,這已經不是行車不規範,親人兩行淚能控制的了。

於是萬能的人類發明了一鍵啟動按鈕,只要按下這個按鈕,就會啟動Carplay、雨刮器自動感應,空調自動調節、行車燈自動感應功能。這其實也是外觀模式的應用,下面我們看看程式碼例項。

1、定義子系統類Carplay

package com.weiya.mazhichu.designpatterns.facade;

/**
 * <p class="detail">
 * 功能:子系統類:Carplay
 * </p>
 *
 * @author Moore
 * @ClassName Car play.
 * @Version V1.0.
 * @date 2019.07.31 15:21:12
 */
public class CarPlay {

    public void openCarPlay(){
        System.out.println("carplay開啟,可以投影手機導航,或者聽歌了");
    }

    public void closeCarPlay(){
        System.out.println("carplay關閉");
    }
}

2、定義子系統類空調

package com.weiya.mazhichu.designpatterns.facade;

/**
 * <p class="detail">
 * 功能:子系統類:空調
 * </p>
 *
 * @author Moore
 * @ClassName Air conditioning.
 * @Version V1.0.
 * @date 2019.07.31 15:24:16
 */
public class AirConditioning {
    public void openAirConditioningAutoSwitch(){
        System.out.println("空調自動調節開啟");
    }

    public void closeAirConditioning(){
        System.out.println("空調關閉");
    }
}

3、定義子系統類行車燈

package com.weiya.mazhichu.designpatterns.facade;

/**
 * <p class="detail">
 * 功能: 子系統類:行車燈
 * </p>
 *
 * @author Moore
 * @ClassName Driving lamp.
 * @Version V1.0.
 * @date 2019.07.31 15:17:15
 */
public class DrivingLamp {

    public void openAutoSwitchLamp(){
        System.out.println("行車燈自動感應切換開啟");
    }

    public void turnOffLamp(){
        System.out.println("行車燈自動感應關閉");
    }
}

4、定義子系統類雨刮器

package com.weiya.mazhichu.designpatterns.facade;

/**
 * <p class="detail">
 * 功能:子系統類:雨刮器
 * </p>
 *
 * @author Moore
 * @ClassName Wiper.
 * @Version V1.0.
 * @date 2019.07.31 15:26:41
 */
public class Wiper {
    public void openWiperAutoSensor(){
        System.out.println("雨刮器自動感應開啟");
    }

    public void closeWiper(){
        System.out.println("雨刮器關閉");
    }
}

5、定義外觀類(門面類):一鍵啟動按鈕

package com.weiya.mazhichu.designpatterns.facade;

/**
 * <p class="detail">
 * 功能:外觀類(核心角色):一鍵啟動按鈕
 * </p>
 *
 * @author Moore
 * @ClassName One click start button.
 * @Version V1.0.
 * @date 2019.07.31 15:30:51
 */
public class OneClickStartButton {

    private CarPlay carPlay;
    private AirConditioning airConditioning;
    private DrivingLamp drivingLamp;
    private Wiper wiper;

    public OneClickStartButton() {
        this.carPlay = new CarPlay();
        this.airConditioning = new AirConditioning();
        this.drivingLamp = new DrivingLamp();
        this.wiper = new Wiper();
    }

    /**
     * <p class="detail">
     * 功能:啟動
     * </p>
     *
     * @author Moore
     * @date 2019.07.31 15:32:15
     */
    public void start(){
        carPlay.openCarPlay();
        airConditioning.openAirConditioningAutoSwitch();
        drivingLamp.openAutoSwitchLamp();
        wiper.openWiperAutoSensor();
    }

    /**
     * <p class="detail">
     * 功能:熄火
     * </p>
     *
     * @author Moore
     * @date 2019.07.31 15:32:17
     */
    public void flameout(){
        carPlay.closeCarPlay();
        airConditioning.closeAirConditioning();
        drivingLamp.turnOffLamp();
        wiper.closeWiper();
    }
}

6、客戶端呼叫

package com.weiya.mazhichu.designpatterns.facade;

/**
 * <p class="detail">
 * 功能:客戶端,直接和外觀類(門面)打交道,通過外觀類訪問子系統
 * </p>
 *
 * @author Moore
 * @ClassName Client.
 * @Version V1.0.
 * @date 2019.07.31 15:36:24
 */
public class Client {

    public static void main(String[] args) {
        OneClickStartButton button = new OneClickStartButton();
        System.out.println("按下一鍵啟動按鈕,汽車啟動");
        button.start();
        System.out.println("------------------------");
        System.out.println("按下一鍵啟動按鈕,汽車熄火");
        button.flameout();
    }


}

檢視執行結果:

通過示例,我們可以看出,客戶端和子系統的互動都是通過外觀類來進行的,客戶端不需要知道子系統內部的實現,只需要跟facade互動即可,降低了客戶端和子系統之間的耦合性,同時和客戶端互動的物件減少,也使得客戶端的程式碼變得簡單。

可以說,外觀模式在我們日常生活中隨處可見,開發中也形影不離,像mybatis-generator,只需要通過一個外觀類,就可以自動生成dao層、mapper層、service層的程式碼,不需要一級級去生成。還有tomcat、slf4j、spring jdbc等也用到外觀模式,這兒不做深入了,感興趣的同學自己去了解一下。

最後,我們來總結一下外觀模式。

優點:

  • 鬆散耦合:使得客戶端和子系統之間解耦,讓子系統內部的模組功能更容易擴充套件和維護。

  • 簡單易用:客戶端根本不需要知道子系統內部的實現,或者根本不需要知道子系統內部的構成,它只需要跟Facade類互動即可。

  • 更好的劃分訪問層次:有些方法是對系統外的,有些方法是系統內部相互互動的使用的。子系統把那些暴露給外部的功能集中到門面中,這樣就可以實現客戶端的使用,很好的隱藏了子系統內部的細節。

**缺點:**不引入抽象外觀類的情況,違背了開閉原則。

適用場景:

  • 對於一個複雜的子系統,需要為使用者提供一個簡單的互動操作。

  • 不希望客戶程式碼和子系統中的類有耦合,以便提高子系統的獨立性和可移植性。

  • 在層次化結構中,可以使用外觀模式定義系統中每一層的入口,層與層之間不直接產生聯絡,而通過外觀類建立聯絡,降低層之間的耦合度。

 

我不能保證我寫的文章都是正確的,但是我能保證都是我自己花時間用心寫的,所有的程式碼示例都是原創,所有的理解都只是我個人理解,不能代表官方權威,所以請各位讀者閱讀時帶著批判的眼光,有選擇性的認同,謝謝!

如果覺得本文有用,請推薦給您身邊的人或者同行關注“碼之初”公眾號,讓我們一起前行,謝謝!

如果發現文章中有問題或者程式碼裡有bug,歡迎留言,請隨時批評指正,謝謝!

相關推薦

Java設計模式系列十三外觀模式

故事一 A:聽說最近出了某款遊戲超好玩,但是我電腦帶不起來,需要個組裝機玩遊戲。 B:你說XX遊戲嗎?真的很好玩,筆記本玩不了

Java】 集合系列01總體框架

Java集合是Java提供的工具包,包含了常用的資料結構:集合、連結串列、佇列、棧、陣列、對映等。 Java集合工具包的位置是Java.util.*。 Java集合主要可以劃分為四個部分:List列表、Set集合、Map對映、工具類(Iterator迭代器、

資料結構與算法系列十三選擇排序

1.引子 1.1.為什麼要學習資料結構與演算法? 有人說,資料結構與演算法,計算機網路,與作業系統都一樣,脫離日常開發,除了面試這輩子可能都用不到呀! 有人說,我是做業務開發的,只要熟練API,熟練框架,熟練各種中介軟體,寫的程式碼不也能“飛”起來嗎? 於是問題來了:為什麼還要學習資料結構與演算法呢? #理

JAVA設計模式之門面模式外觀模式

醫院的例子   現代的軟體系統都是比較複雜的,設計師處理複雜系統的一個常見方法便是將其“分而治之”,把一個系統劃分為幾個較小的子系統。如果把醫院作為一個子系統,按照部門職能,這個系統可以劃分為掛號、門診、劃價、化驗、收費、取藥等。看病的病人要與這些部門打交道,就如同一個子系

Java設計模式系列前言

開發十年,就只剩下這套架構體系了! >>>   

原創我眼中的設計模式系列之簡單工廠模式(一)

int 業務 text 們的 acc 現在 rgs sub reat 簡單工廠模式   在日常的軟件開發中,我們一般都是按照模塊來劃分工作的。 場景一:   試想我們現在有這麽一個模塊,為其他的模塊提供服務,比如說我們調用了好幾個外部接口,統一返回XML字符串,每個接口返回

C#設計模式十三模板方法模式Template Method Pattern【行為型】

並集 client 變化 args 集中 pac 爸爸 rim 自己 原文:C#設計模式之十三模板方法模式(Template Method Pattern)【行為型】一、引言 “結構型”的設計模式已經寫完了,從今天我們開始講“行為型”設計模式。現在我們開始講【行為型】設

C#設計模式系列:橋接模式Bridge

span -i 原來 派生 引用 分享圖片 on() 版本 nta 1.1定義 當一個抽象可能有多個實現時,通常用繼承來進行協調。抽象類定義對該抽象的接口,而具體的子類則用不同的方式加以實現。繼承機制將抽象部分與它的實現部分固定在一起,使得難以對抽象部分和實現部分獨立地進行

c#設計模式系列:模板方法模式Template Method Pattern

出了 strong view crete question ron 屬於 png 過多 引言 提到模板,大家肯定不免想到生活中的“簡歷模板”、“論文模板”、“Word中模版文件”等,在現實生活中,模板的概念就是——有一個規定的格式,然後每個人都可以根據自己的需求或情況去更

設計模式系列 - 目錄持續更新中。。。

為了能在以後的工作學習中少寫 BUG,我覺得還是有必要認真複習一下所有的設計模式, 為了後續系列部落格做技術儲備,槓精 請出門右拐點選 關閉 按鈕即可。需要說明一點的是,設計模式與語言無關,所以還請各位萌新不要陷入語言妄想症。 前言 關於什麼是設計模式,這裡簡單描述描述一下: 所謂設計模

java設計模式個人總結第一篇

java設計模式可將其分為三種類型:建立型、結構型、行為型。 建立型有:    工廠模式(Factory)單例模式(singleton)Builder模式(生成器模式)原型模式(Prototype) 壹.工廠模式(Factory)(典型案例:製造商品流水)

設計模式【Facade模式外觀模式

Facade模式(外觀模式) 為子系統中的一組介面提供一個統一的介面。Facade模式定義了一個更高層的介面,使系統更容易使用。 Facade模式 關鍵特徵 意圖 希望簡化 原系統的使用方

遊戲中的設計模式外觀模式

寫在前面 在遊戲中一個場景可能需要與多個系統進行資訊互動,比如戰鬥系統,揹包系統,經濟系統等 在編寫程式碼時候勢必要將各個系統之間的通訊和依賴降低到儘可能的小 這時候適合使用外觀模式,將應用程式只能看到外觀(facade)物件,不必理會內部的細節物件,從而降低應用程式的複雜

設計模式之門面模式外觀模式 十一

說到了門面模式,有些地方又叫做外觀模式,這個模式在平時做Web專案中應該是經常用到,像我們的Service層與DAO層,就是用到了門面模式,Controller層本來是需要跟一個個DAO打交道,但是有了Service層,它直接與DAO打交道,Controller就可以直接使用

設計模式學習總結:外觀模式Facade

1.場景分析 如下圖所示,我們有一個家庭影院系統,其中包含了調音器、擴音器、播放器、劇場光、爆米花機等部分: 然後我們模擬使用這個系統來播放一部電影,則我們需要進行一下操作: //開啟爆米花機,開始爆米花 popper.on() popper.pop(

Java設計模式系列之裝飾者模式

color http span alt uml 9.png 模式 方案 image 裝飾者模式的定義 動態地將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案 裝飾者模式的UML類圖 Java設計模式系列之裝飾者模式

JAVA設計模式之【代理模式】一靜態代理

代理模式 代理模式是物件的結構模式,給一個物件提供一個代理物件,由代理物件控制對原物件的引用。我們可以通過操作代理物件實現對原物件的呼叫。 本文主要講述靜態代理,jdk動態代理,cglib動態代理三種。 代理的種類 - 遠端(Remo

設計模式總結之Facade Pattern外觀模式

目錄 建立型設計模式: 結構型設計模式: 行為型設計模式: Facade Pattern(外觀模式) 意圖 為子系統中的一組介面提供一個一致的介面,Facade模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。適用性 * 當你要為一個複雜子系統提供一個簡單介

設計模式(c++)筆記之二十三Interpreter模式

一、描述:       概念:給定一個語言,定義它的文法的一種表示,並定義一個直譯器,這個直譯器使用該表示來解釋語言中的句子。 最簡單的例子是表示式運算。       Interpreter

編程經常使用設計模式具體解釋--上篇工廠、單例、建造者、原型

-a 裝飾器模式 nds support art 類的繼承 兩個 開放 lose 參考來自:http://zz563143188.iteye.com/blog/1847029 一、設計模式的分類 整體來說設計模式分為三大類: 創建型模式。共五種:工廠方法模式、抽