設計模式——外觀設計模式(結構型)

摘要

本文介紹了外觀設計模式,它是一種結構型設計模式,通過引入一個外觀類來封裝復雜子系統的調用細節,對外提供簡單統一的接口。文中通過生活類比、關鍵角色介紹、使用場景分析以及結構說明等方面對這一模式進行了全面闡述,還涉及了實現方式、適合場景、實戰示例和相關思考,有助于讀者深入理解外觀設計模式的原理和應用。

1. 外觀設計模式定義

為復雜子系統提供一個統一的高層接口,使得子系統更易使用。外觀模式通過引入一個“外觀類(Facade)”,封裝內部子系統的調用細節,對外暴露一個簡單、統一的接口,隱藏系統的復雜性

1.1. 📦 舉個通俗例子(生活類比):

點外賣 = 外觀模式:

你使用美團 App 點外賣,只用點菜、下單,不需要關心

  • 餐廳是否接單(子系統 A)
  • 騎手怎么接單(子系統 B)
  • 結算怎么走賬(子系統 C)

這就是“外觀類”統一封裝的行為。

1.2. ? 關鍵角色:

角色

說明

Facade(外觀)

高層接口,封裝子系統的復雜邏輯,對外提供簡潔接口。

SubSystem(子系統)

一組類或模塊,完成具體業務邏輯。外觀類內部會協調調用它們。

Client(客戶端)

只依賴外觀類,屏蔽了對內部子系統的直接訪問

1.3. ? 使用場景:

  • 系統結構復雜,希望對外提供簡化接口;
  • 多個系統或模塊集成,希望統一接入方式;
  • 用于分層架構(如 Controller -> Service -> Facade -> Subsystem);
  • 舊系統封裝重構:用外觀封裝老接口,屏蔽調用細節。

2. 外觀設計模式結構

外觀模式包含如下角色:

  • Facade: 外觀角色
  • SubSystem:子系統角色

2.1. 外觀設計模式類圖

2.2. 外觀設計模式時序圖

3. 外觀設計模式實現方式

外觀設計模式(Facade Pattern)的實現方式非常清晰明確:通過封裝多個子系統的復雜調用邏輯,統一對外提供一個簡單接口。

3.1. ? 實現步驟(標準實現方式)

3.1.1. 🔹 步驟 1:定義多個子系統(SubSystem)類

@Service
public class RiskScoreService {public int getRiskScore(String userId) {System.out.println("計算用戶風險分...");return 75;}
}@Service
public class BlacklistService {public boolean isBlacklisted(String userId) {System.out.println("檢查黑名單...");return false;}
}@Service
public class CreditService {public int getCreditLimit(String userId) {System.out.println("獲取信用額度...");return 5000;}
}

3.1.2. 🔹 步驟 2:定義外觀類(Facade)

@Servcie
public class RiskFacade {@Autowiredprivate final RiskScoreService riskScoreService;@Autowiredprivate final BlacklistService blacklistService;@Autowiredprivate final CreditService creditService;public void assessUserRisk(String userId) {System.out.println("開始用戶風控評估...");if (blacklistService.isBlacklisted(userId)) {System.out.println("用戶被拉黑,拒絕服務!");return;}int score = riskScoreService.getRiskScore(userId);int credit = creditService.getCreditLimit(userId);System.out.println("風控評估完成,風險分:" + score + ",信用額度:" + credit);}
}

3.1.3. 🔹 步驟 3:客戶端只使用 Facade,不關心子系統

public class Client {public static void main(String[] args) {RiskFacade facade = new RiskFacade();facade.assessUserRisk("user123");}
}

3.2. ? 在 Spring 項目中的實現方式

如果項目使用 Spring 框架,我們通常會將子系統類標記為 @Service,將外觀類作為一個統一入口暴露:

3.2.1. 🔹 子系統類(Spring Bean)

@Service
public class RiskScoreService { ... }@Service
public class BlacklistService { ... }@Service
public class CreditService { ... }

3.2.2. 🔹 外觀類作為統一接口

@Servcie
public class RiskFacade {@Autowiredprivate RiskScoreService riskScoreService;@Autowiredprivate BlacklistService blacklistService;@Autowiredprivate CreditService creditService;public void assess(String userId) {// 同上,統一調用子服務}
}

3.2.3. 🔹 Controller 層只依賴外觀類

@RestController
@RequestMapping("/risk")
public class RiskController {@Autowiredprivate RiskFacade riskFacade;@GetMapping("/assess")public String assess(@RequestParam String userId) {riskFacade.assess(userId);return "評估完成";}
}

3.3. ? 總結:外觀模式實現要點

步驟

內容

把多個子系統服務拆分成獨立類

建立一個 Facade

類,對外暴露統一方法

客戶端只與 Facade

類交互

④(Spring)

把子系統類交給 Spring 管理,外觀類通過注入協調調用

4. 外觀設計模式適合場景

4.1. ? 適合使用外觀設計模式的場景

場景

說明

系統結構復雜

系統由多個子系統組成,接口調用復雜,客戶端需要簡化調用流程。

統一訪問入口

需要為多個子系統提供一個統一的接口,客戶端只需調用這個接口。

分層架構設計

在分層架構中,用外觀層屏蔽底層子系統的實現細節,降低耦合度。

系統重構與遷移

需要將舊系統接口封裝,兼容老舊代碼,逐步遷移到新系統。

多子系統協調

需要協調多個子系統的調用順序或組合調用邏輯,外觀類負責協調。

4.2. ? 不適合使用外觀設計模式的場景

場景

原因

系統簡單

業務流程簡單,接口調用不復雜,使用外觀反而增加額外層次和復雜度。

單一功能模塊

只涉及一個功能模塊,沒有必要額外封裝統一接口。

頻繁變動接口

子系統接口頻繁改變,外觀層也需頻繁修改,維護成本高。

業務高度耦合

業務流程需要客戶端靈活控制子系統內部調用,外觀隱藏細節不合適。

5. 外觀設計模式實戰示例

下面是一個金融風控場景下的外觀設計模式實戰示例,演示如何用Spring管理所有對象,并且使用注解方式注入,避免構造函數注入,方便集成和維護。

5.1. 項目背景

風控系統需要對用戶進行風險評估,涉及多個子系統服務:

  • 黑名單查詢服務(BlacklistService)
  • 風險分數計算服務(RiskScoreService)
  • 信用額度服務(CreditService)

通過外觀模式(RiskFacade)統一暴露給業務調用層,隱藏各子系統復雜調用。

5.2. 子系統服務類

@Service
public class BlacklistService {public boolean isBlacklisted(String userId) {System.out.println("檢查用戶是否在黑名單中...");// 模擬黑名單檢查邏輯return "blacklistedUser".equals(userId);}
}@Service
public class RiskScoreService {public int calculateRiskScore(String userId) {System.out.println("計算用戶風險分數...");// 模擬風險分數計算return 80;}
}@Service
public class CreditService {public int getCreditLimit(String userId) {System.out.println("獲取用戶信用額度...");// 模擬信用額度查詢return 10000;}
}

5.3. 外觀類

@Component
public class RiskFacade {@Autowiredprivate BlacklistService blacklistService;@Autowiredprivate RiskScoreService riskScoreService;@Autowiredprivate CreditService creditService;public void assessUserRisk(String userId) {System.out.println("=== 開始風控評估 ===");if (blacklistService.isBlacklisted(userId)) {System.out.println("用戶 " + userId + " 在黑名單中,拒絕服務!");return;}int riskScore = riskScoreService.calculateRiskScore(userId);int creditLimit = creditService.getCreditLimit(userId);System.out.println("用戶 " + userId + " 風險分數: " + riskScore);System.out.println("用戶 " + userId + " 信用額度: " + creditLimit);System.out.println("=== 評估結束 ===");}
}

5.4. Controller 層示例

@RestController
@RequestMapping("/risk")
public class RiskController {@Autowiredprivate RiskFacade riskFacade;@GetMapping("/assess")public String assessRisk(@RequestParam String userId) {riskFacade.assessUserRisk(userId);return "風控評估完成";}
}

說明

  • 所有類都由Spring管理,使用 @Service@Component 注解。
  • 外觀類 RiskFacade 注入所有子系統服務,作為統一調用入口。
  • 業務層(Controller)只調用外觀類接口,避免直接依賴多個子系統。
  • 避免構造函數注入,使用 @Autowired 注解實現自動注入,符合你的要求。

6. 外觀設計模式思考

6.1. 門面設計設計模式和DDD中Facade設計區別

6.1.1. 門面設計模式(Facade Pattern)

  • 定義:Facade 是一種結構型設計模式,用于為復雜的子系統提供一個簡化的統一接口。它屏蔽了系統的復雜性,客戶端通過門面類與子系統交互,而無需直接了解子系統的實現細節。
  • 關注點:簡化接口,降低客戶端與子系統之間的耦合。
  • 典型用途
    • 為一個復雜系統提供統一的入口。
    • 隱藏子系統的內部復雜邏輯。
    • 提高客戶端調用的便利性。

6.1.2. DDD 中的 Facade

  • 定義:在領域驅動設計中,Facade 是一個用于協調多個領域對象領域服務的接口或類。它通常用于應用層,作為應用服務的一部分,負責將客戶端的請求轉化為對領域層的調用。
  • 關注點:隔離應用層與領域層,簡化應用層與外部系統(如 UI、接口調用等)的交互。
  • 典型用途
    • 在應用層對外暴露接口。
    • 封裝復雜的領域操作,協調多個領域對象和領域服務。
    • 承載用例(Use Case)的實現邏輯。

6.1.3. 核心區別

維度

門面設計模式(Facade Pattern)

DDD 中的 Facade

目的

為復雜子系統提供一個統一、簡化的接口,屏蔽系統內部實現細節。

為外部系統(如 UI 層、API 層)提供對領域層的調用接口。

適用范圍

用于封裝技術組件(子系統、模塊、服務)。

用于封裝領域邏輯,暴露領域行為。

位置

通常在技術實現層,用于協調多個技術模塊。

通常在應用層,調用領域層服務或聚合根。

關注點

簡化客戶端調用,隱藏子系統復雜性。

承載用例邏輯,協調領域對象和服務,實現業務需求。

是否直接操作領域

通常不直接操作領域對象,只封裝系統內部的模塊調用。

直接操作領域對象、聚合根、領域服務等。

6.2. 門面設計模式(Facade Pattern)的設計思想與 Application 層 的職責相似

6.2.1. Application層與門面模式(Facade Pattern)

Application 層(DDD 中的角色)

  • 主要職責
    • 提供用例邏輯(Use Case)服務。
    • 負責協調領域層(Domain Layer)的多個領域對象、領域服務和聚合根。
    • 為外部系統(如 API 層、UI 層等)提供統一的調用接口。
    • 不包含業務邏輯,業務邏輯屬于領域層,它僅負責調度領域邏輯
  • 核心思想
    • 簡化外部調用(UI 層或 API 層)對復雜領域邏輯的訪問。
    • 將應用層與領域層隔離,保證領域層專注于業務規則,而應用層處理系統操作的組合與流程。

門面模式(Facade Pattern)

  • 主要職責
    • 為子系統提供一個統一接口,屏蔽系統內部的復雜性。
    • 將多個子系統或模塊的調用邏輯封裝在一個類中,外部調用方無需了解子系統的細節。
    • 簡化客戶端調用,降低外部代碼與子系統的耦合度。
  • 核心思想
    • 提供一個簡化的、高層次的接口來調用內部復雜的邏輯或子系統。

6.2.2. Application 層和門面模式的相似性

維度

Application 層

門面模式(Facade Pattern)

主要職責

調用領域層的對象和服務,為外部系統提供統一的調用接口。

調用子系統的服務,為客戶端提供簡化的調用入口。

目標

簡化外部系統對復雜領域邏輯的調用,協調領域服務和對象。

隱藏子系統的復雜性,為客戶端提供簡化的接口。

隱藏復雜性

隱藏領域層內部對象之間的交互細節。

隱藏子系統之間的交互細節。

調用方

外部系統(UI 層、API 層等)。

客戶端或其他模塊。

實現的粒度

業務用例為單位,封裝一個完整的應用邏輯。

技術組件為單位,封裝多個模塊或服務的調用邏輯。

結論兩者都承擔了“簡化復雜性、統一接口”的職責,但 Application 層更專注于領域邏輯的編排和業務用例,而門面模式更關注技術子系統的整合和封裝。

6.3. 項目提供RPC 服務接口設計是不是屬于的門面設計模式?

是的,可以認為屬于門面設計模式的應用。門面模式(Facade Pattern)定義:為子系統中的一組復雜接口提供一個統一的高層接口,使子系統更易使用。

Spring 中 RPC 服務接口的特點(比如基于 Dubbo、gRPC、Spring Cloud):

特性

說明

📦 對外暴露服務接口

Controller 不再是主角,RPC 接口才是系統“對外的門面”

?? 封裝多個底層業務服務(Service、DAO、組件等)

對外提供統一調用入口

🔐 對調用者隱藏實現細節

調用方只知道接口,內部邏輯對其不可見

🔌 提供遠程訪問能力

一般用于微服務、分布式系統間通信

這與門面模式的核心思想高度一致:對復雜子系統提供統一、簡潔、高層次的訪問接口。示例場景:

假設你有一個貸款審批系統,下游調用方只需調用如下 RPC 接口:

public interface LoanApprovalRpcService {ApprovalResult approveLoan(LoanApplicationDTO application);
}

而這個接口內部其實會:

  • 校驗申請數據
  • 調用風控系統
  • 查詢信用評分
  • 寫入審批日志
  • 通知第三方平臺

這時你暴露的這個 RPC 接口就非常標準地扮演了“門面”角色

  • 對外隱藏了所有復雜的邏輯
  • 調用者只需要關心一個方法:approveLoan(...)

博文參考

  • 4. 外觀模式 — Graphic Design Patterns
  • 外觀設計模式(門面模式)

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

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

相關文章

LabVIEW磁懸浮軸承傳感器故障識別

針對工業高端裝備中主動磁懸浮軸承(AMB)的位移傳感器故障檢測需求,基于 LabVIEW 平臺構建了一套高精度故障識別系統。通過集成品牌硬件與 LabVIEW 的信號處理能力,實現了傳感器探頭故障的實時監測與精準定位,解決了傳統…

集成學習三種框架

集成學習通過組合多個弱學習器構建強學習器,常見框架包括Bagging(裝袋)、Boosting(提升) 和Stacking(堆疊) 一、Bagging(自助裝袋法) 核心思想 從原始數據中通過有放回…

PCI DSS培訓記錄

22日上午: 整體PCI DSS 結構分享VISA分享全球欺詐風險動態 信用卡被偷枚舉攻擊依然是最為主要的安全威脅之一(枚舉驗證碼),增加3DS驗證防護勒索軟件和信息泄漏攻擊欺詐分子對AI技術的興趣日益增加,如換臉軟件過驗證基于NFC技術利用非接交易進行欺詐成為新的攻擊手段,如NF…

數據安全中心是什么?如何做好數據安全管理?

目錄 一、數據安全中心是什么 (一)數據安全中心的定義 (二)數據安全中心的功能 1. 數據分類分級 2. 訪問控制 3. 數據加密 4. 安全審計 5. 威脅檢測與響應 二、數據安全管理的重要性 三、如何借助數據安全中心做好數據安…

黑馬Java面試筆記之 微服務篇(業務)

一. 限流 你們項目中有沒有做過限流?怎么做的? 為什么要限流呢? 一是并發的確大(突發流量) 二是防止用戶惡意刷接口 限流的實現方式: Tomcat:可以設置最大連接數 可以通過maxThreads設置最大Tomcat連接數,實現限流,但是適用于單體架構 Nginx:漏桶算法網關,令牌桶算法自定…

PostgreSQL的擴展 passwordcheck

PostgreSQL的擴展 passwordcheck passwordcheck 是 PostgreSQL 內置的一個密碼復雜度檢查擴展,用于強制實施基本的密碼策略。 一、擴展概述 功能:在創建或修改用戶密碼時檢查密碼復雜度目的:防止使用過于簡單的密碼適用版本:Po…

Go語言學習-->編譯器安裝

Go語言學習–>編譯器安裝 Go采用的是UTF-8編碼的文本文件存放源代碼,理論上使用任何一款文本編輯器都可以做Go語言開發。這里推薦使用VS Code和Goland。 VS Code是微軟開源的編輯器,而Goland是jetbrains出品的付費IDE。我們這里使用VS Code …

基于Android的一周穿搭APP的設計與實現 _springboot+vue

開發語言:Java框架:springboot AndroidJDK版本:JDK1.8服務器:tomcat7數據庫:mysql 5.7數據庫工具:Navicat12開發軟件:eclipse/myeclipse/ideaMaven包:Maven3.6 系統展示 APP登錄 A…

井字棋——ai PK you

挑戰人工智能,體驗經典井字棋的對決!AI 擁有強大的邏輯計算能力,每一步都經過精準推演。你能戰勝它嗎?還是會被 AI 徹底碾壓? 特點: 智能 AI,難度可調 極簡界面,快速上手 實時勝負…

關于easyx頭文件

一、窗口創建 &#xff08;1&#xff09;幾種創建方式 #include<easyx.h>//easyx的頭文件 #include<iostream> using namespace std;int main() {//創建一個500*500的窗口//參數為&#xff1a;長度&#xff0c;寬度&#xff0c;是否顯示黑框&#xff08;無參為不…

【學習記錄】Django Channels + WebSocket 異步推流開發常用命令匯總

文章目錄 &#x1f4cc; 摘要&#x1f9f0; 虛擬環境管理? 創建虛擬環境? 刪除虛擬環境? 激活/切換虛擬環境 &#x1f6e0;? Django 項目管理? 查看 Django 版本? 創建 Django 項目? 創建 Django App &#x1f4ac; Channels 常用操作? 查看 Channels 版本 &#x1f50…

Java線程狀態及其流轉

在Java編程中&#xff0c;線程是一種重要的并發實體。為了更好地理解和管理多線程應用程序&#xff0c;我們需要清楚線程的不同狀態及其流轉機制。本文將詳細介紹Java中線程的幾種主要狀態以及它們之間的轉換關系。 一、線程狀態概述 Java線程的生命周期有多個狀態&#xff0…

LabVIEW雙光子顯微鏡開發

基于LabVIEW 開發高性能雙光子顯微鏡系統&#xff0c;聚焦于生物樣本深層成像與納米材料三維表征。實現了超快激光控制、多維數據采集與實時圖像重建。系統采用飛秒激光光源與高精度振鏡掃描模塊&#xff0c;結合 LabVIEW 的 FPGA 實時控制能力&#xff0c;可對活體組織、熒光納…

數據庫操作-MySQL-4(JDBC編程)

JDBC&#xff1a;通過Java代碼操作mysql數據庫&#xff0c;數據庫會提供一些API供我們調用 MySQL、Oracle、等API有差異&#xff0c;但是Java統一了所有接口&#xff0c;即JDBC&#xff1b; 原始api-驅動包&#xff08;類似轉接頭&#xff09;-統一的api-Java 驅動包&#xff1…

windows修改躍點數調整網絡優先級

Windows有兩個網卡&#xff0c;一個有線網卡&#xff0c;一個無線網卡&#xff0c;通過修改躍點數來調整優先使用的網卡&#xff0c;這種只是眾多設置方式中的其中一種設置方式 文檔編寫時間&#xff1a;2025年6月 1.打開電腦的網絡連接 cmd--ncpa.cpl 在cmd中運行ncpa.cpl可…

實驗設計與分析(第6版,Montgomery著,傅玨生譯) 第10章擬合回歸模型10.9節思考題10.1 R語言解題

本文是實驗設計與分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅玨生譯) 第10章擬合回歸模型10.9節思考題10.1 R語言解題。主要涉及線性回歸、回歸的顯著性、回歸系數的置信區間。 vial <- seq(1, 10, 1) Viscosity <- c(160,171,175,182,184,181,188,19…

【深入 LangChain 的 Model I/O】提示設計、模型調用與輸出解析全解析

目錄 什么是 Model I/O&#xff1f; 一、提示模板&#xff08;PromptTemplate&#xff09; 1.1 什么是提示模板&#xff1f; 1.2 常見提示模板類型 二、模型調用&#xff08;Model Predict&#xff09; 三、輸出解析&#xff08;Output Parser&#xff09; 綜合示例&…

OD 算法題 B卷【跳格子2】

文章目錄 跳格子2 跳格子2 小明和朋友玩跳格子游戲&#xff0c;有n個連續格子組成的圓圈&#xff0c;每個格子有不同的分數&#xff0c;小朋友可以選擇從任意格子起跳&#xff0c;但是不能跳連續的格子&#xff0c;不能回頭跳&#xff0c;也不能超過一圈&#xff0c;給定一個代…

客戶線索商機怎么管?客戶線索商機管理工具哪個好?

做銷售、搞運營的朋友肯定都有過這種煩惱&#xff1a;每天收到海量客戶線索&#xff0c;卻不知道從哪條開始跟進&#xff1b;試了好幾個管理工具&#xff0c;要么功能太復雜&#xff0c;要么用起來不趁手。其實選對客戶線索商機管理工具&#xff0c;就像找到靠譜的 “銷售小助手…

008房屋租賃系統技術揭秘:構建智能租賃服務生態

房屋租賃系統技術揭秘&#xff1a;構建智能租賃服務生態 在房地產租賃市場日益活躍的當下&#xff0c;房屋租賃系統成為連接房東與租客的重要數字化橋梁。該系統集成用戶管理、房屋信息等多個核心模塊&#xff0c;面向管理員、房東和用戶三類角色&#xff0c;通過前臺展示與后…