設計模式之外觀模式詳解(附源代碼)

外觀模式

外觀模式(Facade Pattern)隱藏系統(tǒng)的復雜性,并向客戶端提供了可以訪問系統(tǒng)的接口。這種類型的設計模式屬于結(jié)構(gòu)型模式,它向現(xiàn)有的系統(tǒng)添加一個接口,來隱藏系統(tǒng)的復雜性。

這種模式涉及到一個單一的類,該類提供了客戶端請求的簡化方法和對現(xiàn)有系統(tǒng)類方法的委托調(diào)用。


介紹

意圖:為子系統(tǒng)中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統(tǒng)更加容易使用。

主要解決:降低訪問復雜系統(tǒng)的內(nèi)部子系統(tǒng)時的復雜度,簡化客戶端與之的接口。

何時使用: 1、客戶端不需要知道系統(tǒng)內(nèi)部的復雜聯(lián)系,整個系統(tǒng)只需提供一個"接待員"即可。 2、定義系統(tǒng)的入口。

如何解決:客戶端不與系統(tǒng)耦合,外觀類與系統(tǒng)耦合。

關(guān)鍵代碼:在客戶端和復雜系統(tǒng)之間再加一層,這一層將調(diào)用順序、依賴關(guān)系等處理好。

應用實例: 1、去醫(yī)院看病,可能要去掛號、門診、劃價、取藥,讓患者或患者家屬覺得很復雜,如果有提供接待人員,只讓接待人員來處理,就很方便。 2、JAVA 的三層開發(fā)模式。

優(yōu)點:

  1. 減少系統(tǒng)相互依賴。
  2. 提高靈活性。
  3. 提高了安全性。

缺點:不符合開閉原則,如果要改東西很麻煩,繼承重寫都不合適。

使用場景:

  1. 為復雜的模塊或子系統(tǒng)提供外界訪問的模塊。
  2. 子系統(tǒng)相對獨立。
  3. 預防低水平人員帶來的風險。

注意事項:在層次化結(jié)構(gòu)中,可以使用外觀模式定義系統(tǒng)中每一層的入口。


實現(xiàn)

我們以廚師為例。我們將想要吃的食物告訴廚師,即調(diào)用廚師對象的做菜接口,由廚師做好飯,即廚師屏蔽了做菜 (底層)的實現(xiàn)。

步驟一

創(chuàng)建關(guān)于做菜一系列子功能:

  1. 買菜(Groceries):

    /**
     * @see 做飯第一步,根據(jù)目標買菜
     * @author Thornhill
     *
     */
    public class Groceries {
     private List<String> names;
    
     public Groceries(List<String> names) {
         this.names = names;
     }
    
     public void buy() {
         System.out.println("買了" + names + "菜");
     }
    }
    
    1. 洗菜(Clean):

      /**
       * @see 做菜第二步,清洗菜品
       * @author Thornhill
       *
       */
      public class Clean {
        public void clean(List<String> names) {
            System.out.println("洗" + names + "菜");
        }
      }
      
      1. 烹飪(Cooking):

        /**
         * @see 做菜第三步,烹飪出鍋
         * @author Thornhill
         *
         */
        public class Cooking {
           public void cooking(List<String> names, String foodName) {
               System.out.println("烹飪" + names + "食材," + "產(chǎn)出" + foodName);
           }
        }
        

步驟二

創(chuàng)建門面對象,即廚師(Chef):

/**
 * @see 告訴廚師,將屏蔽底層實現(xiàn),廚師知道買什么菜,怎么做飯。
 * @author Thornhill
 *
 */
public class Chef {
    public void cooking(String foodName) {
        List<String> names = new ArrayList<>();
        switch (foodName) {
        case "西紅柿雞蛋":
            names.add("雞蛋");
            names.add("西紅柿");

            break;
        case "京醬肉絲":
            names.add("肉");
            names.add("蔥");
            break;
        default:
            System.out.println("您的廚師暫時不支持此功能");
            return;
        // break;
        }
        Groceries groceries = new Groceries(names);
        // 完成購買
        groceries.buy();

        Clean clean = new Clean();
        // 完成清洗
        clean.clean(names);

        Cooking cooking = new Cooking();
        // 完成烹飪
        cooking.cooking(names, foodName);
    }
}

步驟三

創(chuàng)建用戶(User)使用:

/**
 * @see 任性的用戶只需要提出需求使用即可,不需要關(guān)注具體的實現(xiàn)細節(jié)
 * @author Thornhill
 *
 */
public class User {

    public static void main(String[] args) {
        Chef chef = new Chef();
        // 把想吃的菜告訴廚師
        chef.cooking("西紅柿雞蛋");
        chef.cooking("京醬肉絲");
        chef.cooking("滿漢全席");
    }

}

步驟四

測試輸出:

買了[雞蛋, 西紅柿]菜
洗[雞蛋, 西紅柿]菜
烹飪[雞蛋, 西紅柿]食材,產(chǎn)出西紅柿雞蛋
買了[肉, 蔥]菜
洗[肉, 蔥]菜
烹飪[肉, 蔥]食材,產(chǎn)出京醬肉絲
您的廚師暫時不支持此功能

結(jié)語:

外觀模式的應用非常廣泛,從系統(tǒng)的輪子到用戶的需求,都是屏蔽了細節(jié),只提供UI。不過要小心使用,因為這將極大程度違背了開閉原則,對將來的修改造成了困擾。

GitHub源代碼

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容