首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 外觀模式實戰:為複雜子系統提供統一高層介面

     編輯:關於C#

前言

當系統包含多個相互依賴的子系統(如:驗證服務、資料存取、日誌、快取、通知)時,客戶端直接與各子系統交互會導致高耦合、使用複雜、測試困難。外觀模式提供一個統一的高層介面,封裝子系統的複雜交互,讓客戶端只需呼叫單一入口方法。本文以「用戶驗證 + 訊息查詢」為例,展示 Message 外觀類別如何封裝 User.Validate() 與 SqlMessage.Get() 兩個子系統操作。

模式結構與角色

  • Subsystem(子系統類別):User(驗證邏輯)、SqlMessage(資料查詢),各自獨立實作單一職責。
  • Facade(外觀):Message 類別,持有子系統參考,提供 Get() 統一入口,內部協調驗證→查詢流程,處理失敗情況。
  • Client(客戶端):僅依賴 Message 外觀,不知曉子系統存在。
外觀模式類別圖

核心程式碼機制深度解析

1. 子系統:獨立職責實作

public class User
{
    public bool Validate(string userId)
    {
        return userId == "admin"; // 簡化:僅 admin 通過
    }
}

public class SqlMessage
{
    public List<MessageModel> Get()
    {
        var l = new List<MessageModel>();
        l.Add(new MessageModel("SQL方式獲取Message", DateTime.Now));
        return l;
    }
}

2. 外觀:封裝協調邏輯

public class Message
{
    private string _userId;

    public Message(string userId) { this._userId = userId; }

    public List<MessageModel> Get()
    {
        User u = new User();
        SqlMessage m = new SqlMessage();

        if (u.Validate(_userId))
            return m.Get(); // 驗證通過 → 查詢資料
        else
        {
            // 驗證失敗 → 回傳預設訊息
            var l = new List<MessageModel>();
            l.Add(new MessageModel("無權獲取", DateTime.Now));
            return l;
        }
    }
}

關鍵設計:

  • 外觀建構子接收必要參數(userId),內部實例化子系統(或注入)。
  • Get() 封裝「驗證→查詢」固定流程,客戶端單次呼叫完成完整業務。
  • 失敗情況內部處理(回傳預設訊息),不拋出異常給客戶端(視業務而定)。
  • 外觀不新增子系統功能,僅組合現有功能。

3. 客戶端:極簡使用


Message m = new Message("user");  // 非 admin
Response.Write(m.Get()[0].Message); // 輸出:無權獲取

m = new Message("admin");         // admin
Response.Write(m.Get()[0].Message); // 輸出:SQL方式獲取Message

執行結果驗證

無權獲取 2007-3-20 22:16:50
SQL方式獲取Message 2007-3-20 22:16:50

客戶端零感知子系統複雜性,同一介面根據參數產生不同結果。

外觀模式 vs 相關模式對比

模式意圖關係
外觀簡化介面,隱藏子系統複雜性單向:外觀→子系統,子系統不知外觀
中介者協調同事間交互雙向:中介者↔同事,同事知中介者
代理控制對單一物件存取代理實作同介面,透明替換真實物件
適配器轉換介面使不相容類別能合作適配器實作目標介面,包裝被適配者

進階應用與最佳實務

多層外觀:分層架構中的外觀層

  • 表現層 → **Application Facade** (Use Case 級) → **Domain Facade** (Aggregate 級) → Repository/Service。
  • 每層外觀只與相鄰層溝通,避免跨層調用。

外觀與依賴注入結合


public class MessageFacade
{
    private readonly IUserService _userService;
    private readonly IMessageRepository _messageRepo;

    public MessageFacade(IUserService userService, IMessageRepository messageRepo)
    {
        _userService = userService;
        _messageRepo = messageRepo;
    }

    public List<MessageModel> GetMessages(string userId)
    {
        if (!_userService.Validate(userId))
            return new List<MessageModel> { new MessageModel("無權獲取", DateTime.Now) };
        return _messageRepo.GetAll();
    }
}

優點:外觀可測試(Mock 子系統)、支援多實現切換、生命週期由容器管理。

避免「上帝外觀」反模式

  • 外觀方法過多(>10-15)暗示職責過重,需拆分為多個領域外觀。
  • 外觀不應包含業務邏輯,僅協調子系統呼叫順序與參數轉換。
  • 子系統之間不應互相依賴,若有依賴說明領域劃分不清。

外觀不強制唯一入口

  • 客戶端仍可直接使用子系統(若需精細控制)。
  • 外觀提供「預設/常用/簡化」路徑,非強制禁用子系統。
  • 文件化標註:哪些屬於外觀 API、哪些屬於進階 API。

優缺點總結

優點

  • 解耦客戶端與子系統:子系統變更不影響客戶端(只改外觀)。
  • 簡化使用:單一入口完成複雜流程,降低學習曲線。
  • 減少編譯依賴:客戶端只編譯依賴外觀,加快建構速度。
  • 便於遷移:舊系統包裝為外觀,新系統漸進替換子系統實作。

缺點

  • 違反開閉原則風險:新增子系統功能需修改外觀(緩解:介面隔離、多外觀)。
  • 可能隱藏過多細節,導致客戶端無法精細控制(提供進階 API 緩解)。
  • 外觀類別可能膨脹為「上帝類別」(嚴格限制職責:僅協調、不含業務邏輯)。

經典應用場景

  • **框架/庫進入點**:DbContext (EF Core)、HttpClient、JsonSerializer。
  • **微服務 API Gateway**:聚合多下游服務呼叫,對外單一介面。
  • **建構器模式中的 Director**:封裝複雜建構步驟。
  • **舊系統包裝**:Legacy Code 封裝為外觀,新系統漸進重構。
  • **跨層協調**:Controller → Application Service (Facade) → Domain Services。

總結

外觀模式以「一個統一介面」化解「複雜子系統」的使用難題。本範例以 Message 封裝 User.Validate() + SqlMessage.Get() 為例,展示了外觀如何將多步驟協調邏輯內部化,為客戶端提供極簡的 Get() 入口。實務中,從資料庫 Context、HTTP Client、序列化器到微服務 Gateway、Application Service,外觀模式是分層架構、模組化設計、第三方庫整合的基石。掌握其核心——「封裝協調、不含業務、非強制唯一、防止膨脹」,能讓你在設計系統邊界、模組介面、遷移策略時,構建出清晰分層、低耦合、易演進的軟體架構。


參考資源:DoFactory Facade Pattern

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved