09.外觀模式設計思想
目錄介紹
01.外觀模式基礎
- 1.1 外觀模式由來
- 1.2 外觀模式定義
- 1.3 外觀模式場景
- 1.4 外觀模式思考
- 1.5 解決的問題
02.外觀模式實現
- 2.1 羅列一個場景
- 2.2 外觀結構
- 2.3 外觀基本實現
- 2.4 有哪些注意點
- 2.5 設計思想
03.外觀例項演示
- 3.1 需求分析
- 3.2 程式碼案例實現
- 3.3 是否可以最佳化
- 04.外觀模式場景
05.外觀模式分析
- 5.1 外觀模式優點
- 5.2 外觀模式缺點
- 5.3 適用環境
- 5.4 模式擴充
06.外觀代理總結
- 6.1 總結一下學習
- 6.2 更多內容推薦
推薦一個好玩網站
一個最純粹的技術分享網站,打造精品技術程式設計專欄!程式設計進階網
https://yccoding.com/
01.外觀模式基礎
1.0 本部落格AI摘要
外觀模式設計思想:為了解決軟體系統中的複雜性和耦合性問題,外觀模式提供了一組統一的介面,簡化客戶端與子系統的互動。主要內容包括外觀模式的基礎、實現、例項演示、應用場景、優缺點及適用環境。透過建立外觀類,將複雜系統的內部實現細節隱藏起來,只暴露出簡化的介面給客戶端,從而降低耦合度,提高系統的可維護性和可擴充套件性。
1.1 外觀模式由來
外觀模式的由來是為了解決軟體系統中的複雜性和耦合性問題。在大型軟體系統中,各個子系統之間可能存在複雜的依賴關係和互動邏輯,這導致了系統的可維護性和可擴充套件性變得困難。為了簡化客戶端與子系統之間的互動,外觀模式被引入。
門面模式原理和實現都特別簡單,應用場景也比較明確,主要在介面設計方面使用。更多內容
1.2 外觀模式定義
門面模式,也叫外觀模式,英文全稱是 Facade Design Pattern。
在 GoF 的《設計模式》一書中,門面模式是這樣定義的:Provide a unified interface to a set of interfaces in a subsystem. Facade Pattern defines a higher-level interface that makes the subsystem easier to use.
翻譯成中文就是:門面模式為子系統提供一組統一的介面,定義一組高層介面讓子系統更易用。
外部與一個子系統的通訊必須透過一個統一的外觀物件進行,為子系統中的一組介面提供一個一致的介面,外觀模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。
1.3 外觀模式場景
應用場景:
- 醫院接待:醫院的接待人員簡化了掛號、門診、劃價、取藥等複雜流程。
- Java三層架構:透過外觀模式,可以簡化對錶示層、業務邏輯層和資料訪問層的訪問。
1.4 外觀模式思考
外觀模式的核心思想主要是透過建立一個外觀類,將複雜系統的內部實現細節隱藏起來,只暴露出一個簡化的介面給客戶端。客戶端只需要與外觀類進行互動,而不需要直接與子系統的元件進行互動,從而達到想要的效果。
在思考外觀模式時,可以考慮以下幾個方面:
- 系統的複雜性:外觀模式適用於系統的複雜性較高,包含多個子系統或模組的情況。
- 客戶端的便利性:外觀模式旨在提供一個簡化的介面給客戶端使用,使得客戶端可以更方便地使用系統的功能,而不需要了解系統的內部實現細節。
- 系統的靈活性和可擴充套件性:外觀模式可以提供系統的靈活性和可擴充套件性。
- 設計的一致性和封裝性:外觀模式可以提供設計的一致性和封裝性。
1.5 解決的問題
主要解決的問題
- 降低客戶端與複雜子系統之間的耦合度。
- 簡化客戶端對複雜系統的操作,隱藏內部實現細節。更多內容
02.外觀模式實現
2.1 羅列一個場景
下面透過一個簡單的例子來演示。假設有一個電腦系統,包含了多個子系統,如音樂功能、影片功能和聯網功能。可以開啟或者關閉某功能。
2.2 外觀結構
外觀模式包含如下角色:
- Facade: 外觀角色。提供一個簡化的介面,封裝了系統的複雜性。外觀模式的客戶端透過與外觀物件互動,而無需直接與系統的各個元件打交道。
- SubSystem:子系統角色。由多個相互關聯的類組成,負責系統的具體功能。外觀物件透過呼叫這些子系統來完成客戶端的請求。
- Client:客戶端。使用外觀物件來與系統互動,而不需要了解系統內部的具體實現。
2.3 外觀基本實現
實現方式
- 建立外觀類:定義一個類(外觀),作為客戶端與子系統之間的中介。提供Facade介面,抽象出通用方法開啟和關閉。
- 封裝子系統操作:外觀類將複雜的子系統操作封裝成簡單的方法。三個子系統類(Subsystem):音樂功能、影片功能和聯網功能
提供一個簡化的介面
public interface Facade {
void open();
void close();
}
建立三個子系統類(Subsystem):音樂功能、影片功能和聯網功能。更多內容
public class Music implements Facade{
@Override
public void open() {
System.out.println("載入音樂");
}
@Override
public void stop() {
System.out.println("關閉音樂");
}
}
public class Video implements Facade{
@Override
public void open() {
System.out.println("開啟影片");
}
@Override
public void stop() {
System.out.println("關閉影片");
}
}
public class Internet implements Facade{
@Override
public void open() {
System.out.println("連線網路");
}
@Override
public void stop() {
System.out.println("斷開網路");
}
}
建立外觀類(Facade) - 電腦系統
public class Computer {
private Music music;
private Video video;
private Internet internet;
public Computer() {
this.music = new Music();
this.video = new Video();
this.internet = new Internet();
}
public void openVideo() {
internet.open();
music.open();
video.open();
}
public void stopVideo() {
video.stop();
music.stop();
internet.stop();
}
}
建立客戶端(Client)
private void test() {
Computer computer = new Computer();
System.out.println("播放影片步驟:");
// 播放影片
computer.openVideo();
System.out.println("關閉影片步驟:");
// 關閉影片
computer.stopVideo();
}
在上述例子中,音樂功能、影片功能和聯網功能是子系統,Computer是外觀類,封裝了對這些子系統的呼叫,並提供了簡化的介面給客戶端。
在客戶端中,我們使用外觀模式簡化了電腦系統的使用。透過呼叫外觀類的方法,客戶端無需直接與多個子系統互動,而是透過外觀類來管理對子系統的呼叫。直接一個介面呼叫開啟影片,開啟音樂,連線網路功能
該案例中思考:如果不使用外觀模式,客戶端通常需要和子系統內部的多個模組互動,也就是說客戶端會和這些模組之間都有依賴關係,任意一個模組的變動都可能會引起客戶端的變動。
使用外觀模式後,客戶端只需要和外觀類互動,即只和這個外觀類有依賴關係,不需要再去關心子系統內部模組的變動情況了。更多內容,這樣一來,客戶端不但簡單,而且這個系統會更有彈性。
2.4 有哪些注意點
外觀模式並不是為了解決系統的效能問題,而是為了提供一個簡化的介面和封裝系統的複雜性。在使用外觀模式時,需要權衡封裝的程度和靈活性,並根據具體的需求和情況做出決策。
2.5 設計思想
比如該案例中:
- 針對音樂,影片,聯網抽象出通用功能,定義成介面【開啟和關閉】。充分體現出物件導向中抽象的設計思想!
- 針對音樂,影片,聯網各個子系統之間的互動,將他們的邏輯封裝到外觀類中,充分體現出封裝的原則!
外觀模式的設計思想是基於封裝和抽象的原則,透過將子系統的複雜性隱藏起來,提供一個簡化的介面給客戶端使用。這樣可以提高系統的可維護性、可擴充套件性和可重用性,同時也使得客戶端程式碼更加簡潔和易於理解。
03.外觀例項演示
3.1 需求分析
有個需求:我們知道在UI開發中,可以繪製很多影像。比如可以繪製圓形,繪製矩形,繪製橢圓形,繪製……來達到繪製顯示的效果。
我們將建立一個 Shape 介面和實現了 Shape 介面的實體類。下一步是定義一個外觀類 ShapeMaker。更多內容
3.2 程式碼案例實現
建立一個介面。
public interface Shape {
void draw();
}
建立實現介面的實體類。
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle::draw()");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Square::draw()");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Circle::draw()");
}
}
建立一個外觀類。
public class ShapeMaker {
private Shape circle;
private Shape rectangle;
private Shape square;
public ShapeMaker() {
circle = new Circle();
rectangle = new Rectangle();
square = new Square();
}
public void drawCircle(){
circle.draw();
}
public void drawRectangle(){
rectangle.draw();
}
public void drawSquare(){
square.draw();
}
}
使用該外觀類畫出各種型別的形狀。
private void test() {
ShapeMaker shapeMaker = new ShapeMaker();
shapeMaker.drawCircle();
shapeMaker.drawRectangle();
shapeMaker.drawSquare();
}
3.3 是否可以最佳化
比如,現在增加一個需求,繪製各種素材,不管是圓形,矩形,或者橢圓等,都需要建立畫筆和畫板,可以給繪製設定不同的顏色。如果是你,該如何設計!更多內容
05.外觀模式分析
5.1 外觀模式優點
- 簡化介面:外觀模式為子系統提供了一個簡化的介面,使得呼叫者無需關心子系統的內部細節和複雜性,降低了系統的學習成本和使用難度。
- 降低耦合度:透過引入外觀類,子系統與呼叫者之間的耦合度得到了降低。外觀類作為中間層,遮蔽了子系統的具體實現,使得子系統內部的修改不會影響到呼叫者。
- 提高靈活性:由於外觀類提供了統一的介面,呼叫者可以更加靈活地使用子系統,而無需關心子系統的具體實現細節。這有助於增加系統的可擴充套件性和可維護性。
- 易於維護:當子系統內部發生變更時,只需要修改外觀類即可,而無需修改所有呼叫者的程式碼。這大大降低了系統的維護成本。
5.2 外觀模式缺點
- 可能違背開閉原則:當需要新增新的子系統功能時,可能需要修改外觀類或者增加新的外觀類。這在一定程度上違背了開閉原則(即對擴充套件開放,對修改封閉),可能導致系統的穩定性和可維護性受到影響。
- 可能增加不必要的複雜性:在某些情況下,如果子系統本身就很簡單或者呼叫者需要直接訪問子系統的某些功能,引入外觀模式可能會增加不必要的複雜性。
5.3 適用環境
在以下情況下可以使用外觀模式:
- 當要為一個複雜子系統提供一個簡單介面時可以使用外觀模式。該介面可以滿足大多數使用者的需求,而且使用者也可以越過外觀類直接訪問子系統。
- 客戶程式與多個子系統之間存在很大的依賴性。引入外觀類將子系統與客戶以及其他子系統解耦,可以提高子系統的獨立性和可移植性。
- 在層次化結構中,可以使用外觀模式定義系統中每一層的入口,層與層之間不直接產生聯絡,而透過外觀類建立聯絡,降低層之間的耦合度。
5.4 模式擴充
不要試圖透過外觀類為子系統增加新行為
不要透過繼承一個外觀類在子系統中加入新的行為,這種做法是錯誤的。外觀模式的用意是為子系統提供一個集中化和簡化的溝通渠道,而不是向子系統加入新的行為,新的行為的增加應該透過修改原有子系統類或增加新的子系統類來實現,不能透過外觀類來實現。
外觀模式與迪米特法則
外觀模式創造出一個外觀物件,將客戶端所涉及的屬於一個子系統的協作夥伴的數量減到最少,使得客戶端與子系統內部的物件的相互作用被外觀物件所取代。外觀類充當了客戶類與子系統類之間的“第三者”,降低了客戶類與子系統類之間的耦合度,外觀模式就是實現程式碼重構以便達到“迪米特法則”要求的一個強有力的武器。
抽象外觀類的引入
外觀模式最大的缺點在於違背了“開閉原則”,當增加新的子系統或者移除子系統時需要修改外觀類,可以透過引入抽象外觀類在一定程度上解決該問題,客戶端針對抽象外觀類進行程式設計。對於新的業務需求,不修改原有外觀類,而對應增加一個新的具體外觀類,由新的具體外觀類來關聯新的子系統物件,同時透過修改配置檔案來達到不修改原始碼並更換外觀類的目的。
06.外觀代理總結
6.1 總結一下學習
01.外觀模式基礎
外觀模式的由來是為了解決軟體系統中的複雜性和耦合性問題。在大型軟體系統中,各個子系統之間可能存在複雜的依賴關係和互動邏輯,這導致了系統的可維護性和可擴充套件性變得困難。為了簡化客戶端與子系統之間的互動,外觀模式被引入。
定義是:門面模式為子系統提供一組統一的介面,定義一組高層介面讓子系統更易用。更多內容
主要解決的問題
- 降低客戶端與複雜子系統之間的耦合度。
- 簡化客戶端對複雜系統的操作,隱藏內部實現細節。
02.外觀模式實現
假設有一個電腦系統,包含了多個子系統,如音樂功能、影片功能和聯網功能。可以開啟或者關閉某功能。
實現方式
- 建立外觀類:定義一個類(外觀),作為客戶端與子系統之間的中介。提供Facade介面,抽象出通用方法開啟和關閉。
- 封裝子系統操作:外觀類將複雜的子系統操作封裝成簡單的方法。三個子系統類(Subsystem):音樂功能、影片功能和聯網功能
比如該案例中:
- 針對音樂,影片,聯網抽象出通用功能,定義成介面【開啟和關閉】。充分體現出物件導向中抽象的設計思想!
- 針對音樂,影片,聯網各個子系統之間的互動,將他們的邏輯封裝到外觀類中,充分體現出封裝的原則!
03.外觀例項演示
有個需求:我們知道在UI開發中,可以繪製很多影像。比如可以繪製圓形,繪製矩形,繪製橢圓形,繪製……來達到繪製顯示的效果。更多內容
05.外觀模式分析
外觀模式優點:1.簡化介面;2.降低耦合;3.提高靈活性;4.方便維護
外觀模式缺點:1.當新增新的子類系統,可能需要修改外觀類,或者破壞開閉原則;
使用建議:建議1不要透過外觀類給子類系統加入新的行為。
6.2 更多內容推薦
模組 | 描述 | 備註 |
---|---|---|
GitHub | 多個YC系列開源專案,包含Android元件庫,以及多個案例 | GitHub |
部落格彙總 | 匯聚Java,Android,C/C++,網路協議,演算法,程式設計總結等 | YCBlogs |
設計模式 | 六大設計原則,23種設計模式,設計模式案例,物件導向思想 | 設計模式 |
Java進階 | 資料設計和原理,物件導向核心思想,IO,異常,執行緒和併發,JVM | Java高階 |
網路協議 | 網路實際案例,網路原理和分層,Https,網路請求,故障排查 | 網路協議 |
計算機原理 | 計算機組成結構,框架,儲存器,CPU設計,記憶體設計,指令程式設計原理,異常處理機制,IO操作和原理 | 計算機基礎 |
學習C程式設計 | C語言入門級別系統全面的學習教程,學習三到四個綜合案例 | C程式設計 |
C++程式設計 | C++語言入門級別系統全面的教學教程,併發程式設計,核心原理 | C++程式設計 |
演算法實踐 | 專欄,陣列,連結串列,棧,佇列,樹,雜湊,遞迴,查詢,排序等 | Leetcode |
Android | 基礎入門,開源庫解讀,效能最佳化,Framework,方案設計 | Android |
23種設計模式
23種設計模式 & 描述 & 核心作用 | 包括 |
---|---|
建立型模式 提供建立物件用例。能夠將軟體模組中物件的建立和物件的使用分離 | 工廠模式(Factory Pattern) 抽象工廠模式(Abstract Factory Pattern) 單例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern) |
結構型模式 關注類和物件的組合。描述如何將類或者物件結合在一起形成更大的結構 | 介面卡模式(Adapter Pattern) 橋接模式(Bridge Pattern) 過濾器模式(Filter、Criteria Pattern) 組合模式(Composite Pattern) 裝飾器模式(Decorator Pattern) 外觀模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) |
行為型模式 特別關注物件之間的通訊。主要解決的就是“類或物件之間的互動”問題 | 責任鏈模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 直譯器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 備忘錄模式(Memento Pattern) 觀察者模式(Observer Pattern) 狀態模式(State Pattern) 空物件模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 訪問者模式(Visitor Pattern) |
6.3 更多內容
- GitHub:https://github.com/yangchong211
- 我的程式設計網站:https://yccoding.com
- 部落格彙總:https://github.com/yangchong211/YCBlogs
- 設計模式專欄:https://github.com/yangchong211/YCDesignBlog
- Java高階進階專欄:https://github.com/yangchong211/YCJavaBlog
- 網路協議專欄:https://github.com/yangchong211/YCNetwork
- 計算機基礎原理專欄:https://github.com/yangchong211/YCComputerBlog