外觀模式詳細講解
- 一、概念
- 二、 外觀模式結構
- 核心思想及解釋
- 模式的UML類圖
- 模式角色
- 應用場景
- 模式優點
- 模式缺點
- 三、實例演示
- 圖示
- 代碼展示
- 運行結果
一、概念
外觀模式(Facade Pattern)是一種結構型設計模式,它提供了一個統一的接口,用來訪問系統中的一群接口,從而簡化客戶端與系統之間的交互。外觀模式通過引入一個外觀類來封裝子系統的復雜性,使得客戶端只需要與外觀類交互,而無需直接與子系統的各個組件打交道。
二、 外觀模式結構
核心思想及解釋
外觀模式的核心思想是簡化復雜系統的接口。它提供一個統一的接口,客戶端通過這個接口與復雜子系統進行交互,而不需要了解子系統的詳細工作原理。這種模式允許用戶避免直接處理復雜的子系統組件,可以更加簡單地對子系統進行訪問和管理。
模式的UML類圖
模式角色
外觀角色(Facade):這是外觀模式的核心角色,它提供了一個簡化的接口,用于訪問子系統中的功能。外觀類的作用是封裝復雜的子系統操作,讓外部客戶端無需了解內部細節就能進行交互。
子系統角色(Subsystem):這些是實際執行具體任務的類或模塊。它們可能包含多個類和更復雜的邏輯,對于客戶端來說,直接與這些子系統交互可能會非常復雜。
客戶角色(Client):客戶端使用外觀類提供的接口與子系統進行交互。通過這種方式,客戶端可以簡化其代碼,因為它只需要與外觀類打交道,而不是直接與復雜的子系統打交道。
應用場景
1.系統復雜度較高:當系統的某一子系統變得過于復雜,不容易使用時,可以使用外觀模式進行簡化。它可以將系統的復雜性內部化,對外提供一個簡單的接口,使得使用者更加容易使用。
2.系統中存在多個包含關系復雜的接口:當系統中存在多個接口之間的依賴關系比較復雜時,外觀模式可以進行封裝,將復雜性內部化,從而簡化其使用和維護。
3.需要對外封閉系統:當系統需要對外封閉,外界只能通過一個統一的接口來訪問系統時,可以使用外觀模式進行封裝,這樣可以有效提高系統的安全性。
4.系統需要進行重構:當系統需要進行重構,需要對原有的代碼進行優化和改進時,可以使用外觀模式進行重構,使得代碼更加易于理解和維護。同時,使用外觀模式可以將系統功能進行重組,減少耦合,從而提高系統的靈活性和可擴展性。
5.簡化系統接口:客戶端需要使用一個簡單易用的接口來操作整個系統,而不需要關心系統的內部實現。
6.封裝復雜邏輯:系統內部的實現非常復雜,需要通過外觀模式來將其封裝起來,從而便于管理和維護。
7.解耦系統組件:系統內部的各個組件之間存在較高的耦合度,需要通過外觀模式來降低其耦合度,從而提高系統的可擴展性和靈活性。
模式優點
- 簡化接口:客戶端只需與外觀類交互,無需了解系統的復雜性。
- 解耦客戶端和子系統:外觀類作為中介者,降低了客戶端和子系統之間的耦合度。
- 提高靈活性:可以隨時修改外觀類以適應系統變化,而不會影響客戶端代碼。
模式缺點
- 不符合“開閉原則”:如果新增子系統或刪除子系統,可能需要修改外觀角色的代碼,這在一定程度上違反了“開閉原則”。
- 可能隱藏了子系統的復雜性:如果外觀角色設計得過于復雜,可能會隱藏子系統的復雜性,使得客戶端難以理解和使用。
- 封裝過度導致靈活性降低:如果外觀類封裝了過多的子系統功能,可能會導致其變得過于龐大和復雜,反而增加了理解和維護的難度。當需要修改系統內部實現時,可能需要修改外觀類,這可能會影響到其他與外觀類交互的客戶端。
三、實例演示
圖示
代碼展示
package task1;public class GuaHao {private String keshi;public GuaHao(String keshi) {this.keshi = keshi;}public boolean IsTrue() {if (keshi != null) {return true;} elsereturn false;}}
package task1;public class Menzhen {private GuaHao guaHao;public Menzhen(GuaHao guaHao) {this.guaHao = guaHao;}public String check() {String str = "健胃消食片";if (guaHao.IsTrue()) {//判斷是否掛號return str;} elsereturn null;}}
package task1;public class Huajia {private Menzhen menzhen;public Huajia(Menzhen menzhen) {this.menzhen = menzhen;}public double Getprice() {if (menzhen.check() != null) {System.out.println("開的藥是:"+menzhen.check());return 20;} elsereturn 0;}
}
package task1;public class Pay {private Huajia price;public Pay(Huajia price) {this.price = price;}public boolean IsPay() {System.out.println("已繳費" + price.Getprice());return true;}
}
package task1;public class Medicine {public Pay isPay;public Medicine(Pay isPay) {this.isPay = isPay;}public void GetMedicine() {if (isPay.IsPay()) {System.out.println("已取藥");}}}
然后,我們創建一個外觀類,它將子系統的功能進行封裝:
package task1;public class Facade {private GuaHao guaHao;private Menzhen menzhen;private Huajia huajia;private Pay pay;private Medicine medicine;private String keshi;public Facade(String keshi) {this.keshi = keshi;guaHao = new GuaHao(keshi);menzhen = new Menzhen(guaHao);huajia = new Huajia(menzhen);pay = new Pay(huajia);medicine = new Medicine(pay);}public void check() {System.out.println("掛號:"+keshi);medicine.GetMedicine();}}
最后,我們可以在客戶端代碼中使用外觀類:
package task1;public class Test {public static void main(String[] args){Facade facade = new Facade("內科");facade.check();}}
運行結果
在這個示例中,GuaHao
、Menzhen
、Huajia
、Pay
和Medicine
代表子系統中的不同組件,它們各自負責掛號、門診、劃價、付費和取藥。Facade
作為外觀類,提供了一個check()
方法,該方法調用了所有必要的子系統操作來檢查,從而簡化了客戶端的使用。客戶端只需要調用外觀類的一個方法,而無需了解每個子系統的具體實現細節。
"博主用心寫,讀者點關注;互動傳真情,知識不迷路