外觀模式(Facade pattern),又叫門面模式,作用是為一組複雜的方法呼叫提供一個統一的呼叫方法,在這個方法中來實現這組方法的複雜呼叫。
比如我們有一個功能,要依次呼叫A、B、C、D、E 5個方法,這時又有其他幾個功能都要這樣呼叫,哪每個功能都要自己寫一遍如下類似程式碼:
void call() { A(); B(); C(); D(); E();}
哪個功能來呼叫這個邏輯,就要這樣寫一遍,各個功能的呼叫處就顯得臃腫且複雜。
這時我們就需要一個方法來簡化各個呼叫方的程式碼和邏輯,讓呼叫方只關心我呼叫的功能是不是我需要的結果。
外觀模式就登場了,外觀模式為一個功能提供一個統一的方法,而不需要呼叫方去組織被呼叫方的各種業務邏輯,讓呼叫方的使用更加簡單,同時也讓呼叫方和被呼叫方的邏輯解耦。
我們今天就以做菜:炒西紅柿為例子,來演示程式碼。
炒西紅柿這道菜挺簡單,大家基本都會做,大概的流程是:
1、準備食材,準備雞蛋(打雞蛋),洗西紅柿,切西紅柿等;
2、炒雞蛋;
3、炒西紅柿;
4、把西紅柿和雞蛋合炒;;
5、加糖;
6、加鹽;
7、盛盤上菜。
我們炒西紅柿的流程大概如上,步驟其實還挺多(當然每個人的步驟和做法可能稍微有出入),我要自己炒一個就要逐步完成上面的步驟,外觀模式的作用就好比,我不自己做了,我直接下館子或是點外賣,飯館相當於給我提供了一個介面,讓我呼叫一下,稍等幾分鐘,菜就好了,中間的各個環節,對我來說我不用去關心了,這就是外觀模式的意義。
我們來看程式碼。
1、西紅柿炒雞蛋的抽象定義
/** * @Auther: www.itzhimei.com * @Description: */public interface IScrambledEggWithTomato { /** * 準備食材:雞蛋和西紅柿 */ void prepare(); /** * 炒雞蛋 */ void scrambledEgg(); /** * 炒西紅柿 */ void scrambledTomato(); /** * 合起來炒 */ void scrambledEggWithTomato(); /** * 調味:加糖 */ void addSugar(); /** * 調味:加鹽2 */ void addSalt(); /** * 盛盤上菜 */ void finish();}
2、西紅柿炒雞蛋的具體實現
/** * @Auther: www.itzhimei.com * @Description: */public class ScrambledEggWithTomato implements IScrambledEggWithTomato { @Override public void prepare() { System.out.println("準備食材:雞蛋和西紅柿"); } @Override public void scrambledEgg() { System.out.println("炒雞蛋"); } @Override public void scrambledTomato() { System.out.println("炒西紅柿"); } @Override public void scrambledEggWithTomato() { System.out.println("合起來炒"); } @Override public void addSugar() { System.out.println("調味:加糖"); } @Override public void addSalt() { System.out.println("調味:加鹽"); } @Override public void finish() { System.out.println("盛盤上菜"); }}
3、外觀模式 抽象定義
/** * @Auther: www.itzhimei.com * @Description: 外觀模式 抽象定義 */public interface ICookFacade { void cookScrambledEggWithTomato();}
4、外觀模式 實現
/** * @Auther: www.itzhimei.com * @Description: */public class CookFacade implements ICookFacade { IScrambledEggWithTomato scrambledEggWithTomato; public CookFacade(IScrambledEggWithTomato scrambledEggWithTomato) { this.scrambledEggWithTomato = scrambledEggWithTomato; } @Override public void cookScrambledEggWithTomato() { scrambledEggWithTomato.prepare(); scrambledEggWithTomato.scrambledEgg(); scrambledEggWithTomato.scrambledTomato(); scrambledEggWithTomato.scrambledEggWithTomato(); scrambledEggWithTomato.addSugar(); scrambledEggWithTomato.addSalt(); scrambledEggWithTomato.finish(); }}
5、測試
/** * @Auther: www.itzhimei.com * @Description: */public class Client { public static void main(String[] args) { IScrambledEggWithTomato scrambledEggWithTomato = new ScrambledEggWithTomato(); ICookFacade cookFacade = new CookFacade(scrambledEggWithTomato); cookFacade.cookScrambledEggWithTomato(); }}
輸出
準備食材:雞蛋和西紅柿炒雞蛋炒西紅柿合起來炒調味:加糖調味:加鹽盛盤上菜
類關係圖:
最後要說的一點,外觀模式看起來和模板方法模式很像(模板方法模式後面會講到),區別在於,模板方法模式的模板方法中引用的方法都是抽象的,需要子類去實現,這給了子類可按照自己的需要進行變化的靈活性。
而外觀模式簡化了呼叫者的處理邏輯,並且外觀模式的外觀方法,和外觀方法呼叫的方法,都是已經實現的具體邏輯,其重點在於簡化呼叫者的呼叫邏輯。