【設計模式】外觀模式(門面模式)

外觀模式(Facade Pattern)詳解


一、外觀模式簡介

外觀模式(Facade Pattern) 是一種 結構型設計模式,它為一個復雜的子系統提供一個統一的高層接口,使得子系統更容易使用。

外觀模式又稱為門面模式,它是一種對象結構型模式。

簡單來說,外觀模式就像是一個“總控中心”或“門面”,它屏蔽了子系統的復雜性,對外提供一個簡單的調用方式。這樣客戶端不需要了解內部細節,只需要通過這個“門面”來操作整個系統。

外觀模式也是“迪米特法則”的體現。

引入外觀角色之后,用戶只需要直接與外觀角色交互,用戶與子系統之間的復雜關系由外觀角色來實現,從而降低了系統的耦合度。

在這里插入圖片描述
模式結構
在這里插入圖片描述

在這里插入圖片描述
外觀模式包含如下角色
Facade: 外觀角色
SubSystem:子系統角色


二、解決的問題類型

  • 問題背景:當系統中存在多個相互依賴、結構復雜的類和接口時,客戶端直接使用這些類會變得非常麻煩,容易出錯。
  • 解決方案:外觀模式通過引入一個中間層(即外觀類),將這些復雜的交互封裝起來,讓客戶端只需與外觀類打交道即可完成一系列操作。

三、使用場景

  1. 簡化復雜系統的訪問:當你有一個由多個對象組成的子系統,但希望給用戶一個簡單的接口來使用這個系統。
  2. 解耦客戶端與子系統:客戶端不關心子系統內部如何工作,只關心結果。
  3. 分層設計:在多層架構中,外觀常用于表現層與業務邏輯層之間,作為接口抽象層。

四、實際生活案例

想象你在家里使用一個智能音箱說:“我回家了”。這時:

  • 燈自動打開
  • 空調啟動
  • 音樂播放器開始播放你喜歡的音樂
  • 電視自動打開

你并不需要手動去操作每一個設備,而是通過一句話觸發了一個“回家模式”。這個“回家模式”就是外觀類,它封裝了所有設備的操作,對外提供一個統一的入口。


五、代碼案例

典型的外觀角色代碼:

public class Facade
{private SubSystemA obj1 = new SubSystemA();private SubSystemB obj2 = new SubSystemB();private SubSystemC obj3 = new SubSystemC();public void method(){obj1.method();obj2.method();obj3.method();}
} 

場景描述:

我們模擬一個家庭影院系統,包括以下幾個子系統:

  • 投影儀(Projector)
  • 音響(Amplifier)
  • 藍光播放器(BluRayPlayer)
  • 燈光控制(Lights)

我們要通過一個 HomeTheaterFacade 來統一管理這些組件,讓客戶可以通過一個接口輕松地開啟/關閉觀影模式。


子系統類定義:

// 投影儀類
class Projector {public void on() {System.out.println("Projector is ON");}public void setWideScreenMode() {System.out.println("Projector in widescreen mode (16x9)");}public void off() {System.out.println("Projector is OFF");}
}// 音響類
class Amplifier {public void on() {System.out.println("Amplifier is ON");}public void setVolume(int level) {System.out.println("Setting volume to " + level);}public void off() {System.out.println("Amplifier is OFF");}
}// 藍光播放器類
class BluRayPlayer {public void on() {System.out.println("BluRay Player is ON");}public void play(String movie) {System.out.println("Playing movie: " + movie);}public void stop() {System.out.println("BluRay Player stopped");}public void off() {System.out.println("BluRay Player is OFF");}
}// 燈光控制類
class Lights {public void dim(int level) {System.out.println("Lights dimmed to " + level + "% brightness");}public void on() {System.out.println("Lights are ON");}public void off() {System.out.println("Lights are OFF");}
}

案例二:

外觀類實現(Java):

// 家庭影院外觀類
class HomeTheaterFacade {private Projector projector;private Amplifier amplifier;private BluRayPlayer bluRayPlayer;private Lights lights;public HomeTheaterFacade(Projector projector, Amplifier amplifier,BluRayPlayer bluRayPlayer, Lights lights) {this.projector = projector;this.amplifier = amplifier;this.bluRayPlayer = bluRayPlayer;this.lights = lights;}// 開啟觀影模式public void watchMovie(String movie) {System.out.println("Preparing to watch a movie...");lights.dim(10);          // 調暗燈光projector.on();          // 打開投影儀projector.setWideScreenMode(); // 設置寬屏模式amplifier.on();          // 打開音響amplifier.setVolume(85); // 設置音量bluRayPlayer.on();       // 啟動藍光播放器bluRayPlayer.play(movie); // 播放電影}// 關閉觀影模式public void endMovie() {System.out.println("Shutting movie time down...");bluRayPlayer.stop();bluRayPlayer.off();amplifier.off();projector.off();lights.on(); // 燈光恢復}
}

客戶端測試類:

public class Client {public static void main(String[] args) {// 創建各個子系統對象Projector projector = new Projector();Amplifier amplifier = new Amplifier();BluRayPlayer player = new BluRayPlayer();Lights lights = new Lights();// 創建外觀對象HomeTheaterFacade homeTheater = new HomeTheaterFacade(projector, amplifier, player, lights);// 使用外觀開啟觀影模式homeTheater.watchMovie("Inception");System.out.println("\n------------------------------\n");// 使用外觀結束觀影模式homeTheater.endMovie();}
}

輸出結果示例:

Preparing to watch a movie...
Lights dimmed to 10% brightness
Projector is ON
Projector in widescreen mode (16x9)
Amplifier is ON
Setting volume to 85
BluRay Player is ON
Playing movie: Inception------------------------------Shutting movie time down...
BluRay Player stopped
BluRay Player is OFF
Amplifier is OFF
Projector is OFF
Lights are ON

六、優點總結

優點描述
簡化客戶端調用客戶端無需了解子系統細節,只需調用外觀類方法即可
降低耦合度客戶端與子系統解耦,便于后期維護和擴展
提高可維護性修改子系統行為時,只需修改外觀類,不影響客戶端
支持模塊化設計符合高內聚低耦合的設計原則

七、缺點

不能很好地限制客戶使用子系統類,如果對客戶訪問子系統類做太多的限制則減少了可變性和靈活性。

在不引入抽象外觀類的情況下,增加新的子系統可能需要修改外觀類或客戶端的源代碼,違背了“開閉原則”。

八、與其他模式對比(補充)

模式名稱目標
適配器模式解決接口不兼容問題,強調轉換
代理模式控制對某個對象的訪問,強調保護或增強
外觀模式封裝子系統復雜性,強調簡化接口調用

九、小結

  • 外觀模式適用于:需要將一組復雜子系統整合成一個簡單接口供外部使用的場景。
  • 核心思想是:隱藏實現細節,提供統一、簡潔的接口。
  • 作為開發人員,掌握外觀模式有助于我們更好地進行模塊劃分、系統集成和接口設計。

如果你正在開發一個大型系統,比如支付系統、訂單系統、視頻會議系統等,合理使用外觀模式可以大大提升系統的可讀性和可維護性。

如需進一步了解其他設計模式,歡迎繼續提問!

十、擴展內容

  • 一個系統有多個外觀類:在外觀模式中,通常只需要一個外觀類,并且此外觀類只有一個實例,換言之它是一個單例類。在很多情況下為了節約系統資源,一般將外觀類設計為單例類。當然這并不意味著在整個系統里只能有一個外觀類,在一個系統中可以設計多個外觀類,每個外觀類都負責和一些特定的子系統交互,向用戶提供相應的業務功能。
  • 不要試圖通過外觀類為子系統增加新行為:不要通過繼承一個外觀類在子系統中加入新的行為,這種做法是錯誤的。外觀模式的用意是為子系統提供一個集中化和簡化的溝通渠道,而不是向子系統加入新的行為,新的行為的增加應該通過修改原有子系統類或增加新的子系統類來實現,不能通過外觀類來實現。
  • 外觀模式與迪米特法則:外觀模式創造出一個外觀對象,將客戶端所涉及的屬于一個子系統的協作伙伴的數量減到最少,使得客戶端與子系統內部的對象的相互作用被外觀對象所取代。外觀類充當了客戶類與子系統類之間的“第三者”,降低了客戶類與子系統類之間的耦合度,外觀模式就是實現代碼重構以便達到“迪米特法則”要求的一個強有力的武器。
  • 抽象外觀類的引入:外觀模式最大的缺點在于違背了“開閉原則”,當增加新的子系統或者移除子系統時需要修改外觀類,可以通過引入抽象外觀類在一定程度上解決該問題,客戶端針對抽象外觀類進行編程。對于新的業務需求,不修改原有外觀類,而對應增加一個新的具體外觀類,由新的具體外觀類來關聯新的子系統對象,同時通過修改配置文件來達到不修改源代碼并更換外觀類的目的。
    抽象外觀類的引入
    在這里插入圖片描述
    部分內容由AI生成注意識別!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90815.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90815.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90815.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【6.1.1 漫畫分庫分表】

漫畫分庫分表 “數據量大了不可怕,可怕的是不知道如何優雅地拆分。” 🎭 人物介紹 架構師老王:資深數據庫架構專家,精通各種分庫分表方案Java小明:對分庫分表充滿疑問的開發者ShardingSphere師傅:Apache S…

Tomcat問題:啟動腳本startup.bat中文亂碼問題解決

一、問題描述 我們第一次下載或者打開Tomcat時可能在控制臺會出現中文亂碼問題二、解決辦法 我的是8.x版本的tomcat用notepad打開:logging.properties 找到:java.util.logging.ConsoleHandler.encoding設置成GBK,重啟tomcat即可

Linux中Gitee的使用

一、Gitee簡介:Gitee(碼云)是中國的一個代碼托管和協作開發平臺,類似于GitHub或GitLab,主要面向開發者提供代碼管理、項目協作及開源生態服務。適用場景個人開發者:托管私有代碼或參與開源項目。中小企業&a…

Oracle大表數據清理優化與注意事項詳解

一、性能優化策略 1. 批量處理優化批量大小選擇: 小批量(1,000-10,000行):減少UNDO生成,但需要更多提交次數中批量(10,000-100,000行):平衡性能與資源消耗大批量(100,000行):適合高配置環境,但需監控資源使…

Anaconda及Conda介紹及使用

文章目錄Anaconda簡介為什么選擇 Anaconda?Anaconda 安裝Win 平臺macOS 平臺Linux 平臺Anaconda 界面使用Conda簡介Conda下載安裝conda 命令環境管理包管理其他常用命令Jupyter Notebook(可選)Anaconda簡介 Anaconda 是一個數據科學和機器學…

外包干了一周,技術明顯退步

我是一名本科生,自2019年起,我便在南京某軟件公司擔任功能測試的工作。這份工作雖然穩定,但日復一日的重復性工作讓我逐漸陷入了舒適區,失去了前進的動力。兩年的時光匆匆流逝,我卻在原地踏步,技術沒有絲毫…

【QT】多線程相關教程

一、核心概念與 Qt 線程模型 1.線程與進程的區別: 線程是程序執行的最小單元,進程是資源分配的最小單元,線程共享進程的內存空間(堆,全局變量等),而進程擁有獨立的內存空間。Qt線程只要關注同一進程內的并發。 2.為什么使用多線程…

VS 版本更新git安全保護問題的解決

問題:我可能移動了一個VS C# 項目,然后,發現里面的git版本檢測不能用了 正在打開存儲庫: X:\Prj_C#\3D fatal: detected dubious ownership in repository at X:/Prj_C#/3DSnapCatch X:/Prj_C#/3D is owned by:S-1-5-32-544 but the current …

Git常用命令一覽

Git 是基于 Linux內核開發的版本控制工具。與常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本庫的方式,不必服務器端軟件支持(ps:這得分是用什么樣的服務端,使用http協議或者git協議等不太一樣。并且在…

基于 JSON 文件定位圖片缺陷點并保存

基于JSON的圖片缺陷處理流程 ├── 1. 輸入檢查 │ ├── 驗證圖片文件是否存在 │ └── 驗證JSON文件是否存在 │ ├── 2. 數據加載 │ ├── 打開并加載圖片 │ └── 讀取并解析JSON文件 │ ├── 3. 缺陷信息提取 │ ├── 檢查JSON中是否存在shapes字…

Redis基礎學習(五大值數據類型的常用操作命令)

目錄 一、Redis基本知識與Redis鍵(key)常用操作命令。 二、Redis的五大值的數據類型。(value) 三、Redis關于鍵(key)的值常用操作指令表格統計。 (1)字符串(String&#…

Ubuntu——辦公軟件 LibreOffice 安裝與使用指南

十四、LibreOffice 安裝與使用1、核心組件組件????圖標????對應MS Office????核心功能定位????Writer??📝Word專業文檔處理與排版??Calc??📊Excel數據計算與分析??Impress??🎬PowerPoint演示文稿制作??Draw??&…

Securecrt丟失tab以及終端重新配色

今天在使用 Securecrt 的時候,發現 Securecrt 的 tab 標簽消失不見了,仔細回想起來,應該是上一次誤按了 alt enter 最大化,然后導致配置丟失的問題 還有表現就是菜單中的 Session Tabs 無論勾選還是不勾選都沒有任何變化&#xf…

frp搭建內網穿透教程

frp搭建內網穿透教程 步驟1:準備工作 公網服務器:需要一臺具有公網IP的服務器作為中轉服務器,安裝frp服務器端(frps)。內網設備:需要暴露服務的內網設備,安裝frp客戶端(frpc&#xf…

【JavaEE進階】圖書管理系統(未完待續)

目錄 用戶登錄 添加圖書 圖書列表 修改圖書 刪除圖書 批量刪除 攔截器 🍃前言 什么是攔截器? 攔截器的基本使用 自定義攔截器 注冊配置攔截器 攔截路徑 攔截器執行流程 項目實現統一攔截 定義攔截器 注冊配置攔截器 前?圖書管理系統, 咱們只完成了??登錄和圖書列…

基于同花順API的熊市與牛市識別模型開發及因子分析

基于同花順API的熊市與牛市識別模型開發及因子分析 1. 引言 1.1 研究背景與意義 金融市場中的牛市與熊市識別一直是投資者和研究人員關注的重點問題。牛市(Bull Market)通常指價格持續上漲的市場環境,投資者信心充足,交易活躍;而熊市(Bear Market)則指價格持續下跌的市場…

AMD 銳龍 AI MAX+ 395 處理器與端側 AI 部署的行業實踐

2025 年 7 月 10 日,AMD 在深圳召開 Mini AI 工作站行業解決方案峰會,正式發布基于銳龍 AI MAX 395 處理器的端側 AI 部署方案,與 200 余家生態伙伴共同探討 AI 技術在千行百業的落地路徑。這一硬件平臺通過異構計算架構與開放生態設計&#…

期權盤位是什么意思?

本文主要介紹期權盤位是什么意思?“期權盤位”并非金融交易中的標準術語,可能是口語化表達或對某些概念的簡化描述。期權盤位是什么意思?1. 期權盤口的“價位”(買賣報價位置)在期權交易中,“盤口”通常指實…

【Trea】Trea國內版|國際版|海外版下載|Mac版|Windows版|Linux下載配置教程

【Trea】Trea國內版|國際版|海外版下載|Mac版|Windows版下載配置教程 本文適用讀者: 想要第一次安裝 Trea需要在 Windows 或 macOS 上完成環境配置想深入了解 Doubao、DeepSeek、ChatGPT、Claude 等模型在 Trea 中的接…

MyBatis實現分頁查詢-蒼穹外賣筆記

首先分頁查詢的原理是SQL的limit關鍵字。LIMIT 子句用于限制 SQL 查詢返回的記錄數。它接受一個或兩個整數參數,第一個參數表示偏移量,第二個參數表示返回的最大記錄數。我們完全可以使用前端傳給我們的page,pageSize,自己去計算limit的參數,…