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

設計模式精講:代理模式完整實戰與 UML 解析

     編輯:關於C語言

設計模式精講:代理模式完整實戰與 UML 解析

代理模式為某物件提供一個代理者,控制對目標物件的存取。生活中常見例子:明星經紀人(代理)處理商演邀約,明星(真實主題)專注表演。本文以「卓賈易委託戴勵送禮物給嬌嬌」為情境,完整呈現代理模式的 UML 結構、程式碼實作與應用場景。

模式動機與定義

代理模式:提供一個代理物件控制對真實物件的存取。客戶端透過代理間接操作真實物件,兩者實作相同介面,客戶端無感知差異。

適用情境:

  • 遠端代理:隱藏網路通訊細節(RPC、Web Service)
  • 虛擬代理:延遲建立昂貴物件(大圖片載入)
  • 保護代理:控制存取權限(權限檢查)
  • 智慧指標:記錄引用計數、鎖定記憶體

UML 類別圖結構

┌──────────────┐       ┌──────────────┐       ┌──────────────┐
│   Client     │──────▶│   Proxy      │──────▶│  RealSubject │
└──────────────┘       └──────────────┘       └──────────────┘
        │                    │                    │
        │                    │                    │
        ▼                    ▼                    ▼
   使用介面            實作介面              實作介面
   (Subject)          (Subject)             (Subject)
  • Subject:定義真實主題與代理的共同介面
  • RealSubject:真正執行業務邏輯的物件
  • Proxy:持有 RealSubject 參考,控制存取並可附加額外邏輯

情境程式碼實作

#include <cstdio>
#include <string>

// 共同介面:送禮物行為
class IGiveGift {
public:
    virtual ~IGiveGift() = default;
    virtual void GiveDolls() = 0;
    virtual void GiveFlowers() = 0;
    virtual void GiveChocolate() = 0;
};

// 真實主題:被追求者
class SchoolGirl {
public:
    explicit SchoolGirl(const std::string& name) : name_(name) {}
    const std::string& Name() const { return name_; }
private:
    std::string name_;
};

// 代理:追求者(委託者)
class Pursuit : public IGiveGift {
public:
    explicit Pursuit(SchoolGirl* girl) : girl_(girl) {}
    
    void GiveDolls() override {
        printf("%s 送你洋娃娃\n", girl_->Name().c_str());
    }
    void GiveFlowers() override {
        printf("%s 送你鮮花\n", girl_->Name().c_str());
    }
    void GiveChocolate() override {
        printf("%s 送你巧克力\n", girl_->Name().c_str());
    }
private:
    SchoolGirl* girl_;
};

// 代理控制者:朋友戴勵(可加入額外邏輯:記錄、檢查心情等)
class Proxy : public IGiveGift {
public:
    explicit Proxy(SchoolGirl* girl) : pursuit_(girl) {}
    
    void GiveDolls() override {
        // 代理前置邏輯:檢查心情、記錄日誌
        printf("[代理記錄] 準備送洋娃娃給 %s\n", pursuit_.girl_->Name().c_str());
        pursuit_.GiveDolls();
        printf("[代理記錄] 洋娃娃送達完成\n");
    }
    // 其餘方法類似...
private:
    Pursuit pursuit_;  // 組合真實主題
};

// 客戶端使用
int main() {
    SchoolGirl girl("嬌嬌");
    Proxy proxy(&girl);  // 客戶端只認識 Proxy
    
    proxy.GiveDolls();
    proxy.GiveFlowers();
    proxy.GiveChocolate();
    return 0;
}

關鍵設計細節

角色本例類別職責
SubjectIGiveGift定義送禮介面,客戶端面向介面程式設計
RealSubjectPursuit實際執行送禮動作,持有目標女生參考
ProxyProxy控制存取,可添加前置/後置邏輯(日誌、權限、快取)

代理模式變體比較

類型特點典型應用
遠端代理封裝網路通訊gRPC Stub、RMI
虛擬代理延遲初始化大圖片載入、Hibernate 延遲載入
保護代理存取控制Spring AOP 安全攔截
智慧引用引用計數、鎖定std::shared_ptr、COM 介面

C++ 現代化實作建議

  • 使用 std::unique_ptr<RealSubject> 管理生命週期
  • 介面採用純虛擬類別,啟用 final 防止過度繼承
  • 考慮 std::invoke + 完美轉發實作通用代理

總結

代理模式以「間接層」解耦客戶端與真實物件,是控制存取、延遲初始化、分散式系統的基石。掌握其核心在於:代理與真實主題實作相同介面,客戶端無感知差異。實務中常結合裝飾器模式(動態添加行為)或外觀模式(簡化複雜子系統介面)使用。

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