代理模式為某物件提供一個代理者,控制對目標物件的存取。生活中常見例子:明星經紀人(代理)處理商演邀約,明星(真實主題)專注表演。本文以「卓賈易委託戴勵送禮物給嬌嬌」為情境,完整呈現代理模式的 UML 結構、程式碼實作與應用場景。
代理模式:提供一個代理物件控制對真實物件的存取。客戶端透過代理間接操作真實物件,兩者實作相同介面,客戶端無感知差異。
適用情境:
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Client │──────▶│ Proxy │──────▶│ RealSubject │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
│ │ │
▼ ▼ ▼
使用介面 實作介面 實作介面
(Subject) (Subject) (Subject)
#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;
}
| 角色 | 本例類別 | 職責 |
|---|---|---|
| Subject | IGiveGift | 定義送禮介面,客戶端面向介面程式設計 |
| RealSubject | Pursuit | 實際執行送禮動作,持有目標女生參考 |
| Proxy | Proxy | 控制存取,可添加前置/後置邏輯(日誌、權限、快取) |
| 類型 | 特點 | 典型應用 |
|---|---|---|
| 遠端代理 | 封裝網路通訊 | gRPC Stub、RMI |
| 虛擬代理 | 延遲初始化 | 大圖片載入、Hibernate 延遲載入 |
| 保護代理 | 存取控制 | Spring AOP 安全攔截 |
| 智慧引用 | 引用計數、鎖定 | std::shared_ptr、COM 介面 |
std::unique_ptr<RealSubject> 管理生命週期final 防止過度繼承std::invoke + 完美轉發實作通用代理代理模式以「間接層」解耦客戶端與真實物件,是控制存取、延遲初始化、分散式系統的基石。掌握其核心在於:代理與真實主題實作相同介面,客戶端無感知差異。實務中常結合裝飾器模式(動態添加行為)或外觀模式(簡化複雜子系統介面)使用。