【C++ | 设计模式】代理模式的详解与实现

1. 概念

代理模式(Proxy Pattern)是一种结构型设计模式,用于控制对对象的访问。它通过引入代理对象,间接地操作目标对象,从而实现对目标对象的控制。代理模式的核心思想是通过代理对象来控制对目标对象的访问。代理对象在目标对象之前拦截请求,可能对请求进行处理或对目标对象进行延迟加载、权限控制等操作。

2. 模式结构

UML 结构图:

  • Subject(抽象主题):声明了 RealSubject 与 Proxy 的共同接口,定义了某个/些功能。

  • RealSubject(真实主题):通常执行具体的业务逻辑,Proxy 控制对它的访问。

  • Proxy(代理):持有一个 RealSubject 引用(指针),可以在需要时将请求转发给 RealSubject,以此起到代理的作用。

  • Client(客户端):通过 Proxy 间接地与 RealSubject 进行交互。 注意: Proxy 和 RealSubject 都实现了 Subject 的接口,这允许 Client 可以像处理 RealSubject 一样处理 Proxy。

3. 优缺点

优点:

  • 控制访问:代理可以在访问目标对象之前或之后执行附加操作,如检查权限、延迟加载等。
  • 延迟初始化:通过代理实现对目标对象的延迟初始化,直到真正需要时才创建真实对象。
  • 功能扩展:在不修改目标对象的情况下,通过代理可以扩展其功能,如增加日志、缓存等。

缺点:

  • 增加复杂性:引入代理对象可能增加系统的复杂性,尤其是在代理和真实对象之间的接口较多时。
  • 性能开销:代理可能引入额外的性能开销,尤其是在执行额外操作(如权限检查、日志记录)时。

4. 适用场景

  • 延迟加载:需要延迟创建开销较大的对象时。例如,只有在实际需要时才加载图像或数据。
  • 访问控制:在访问目标对象之前需要进行权限验证或其他检查时。例如,控制对某些功能的访问权限。
  • 日志记录:记录对目标对象的访问情况时。例如,记录对某些重要对象的访问日志。
  • 缓存:在代理中缓存目标对象的结果,以避免重复计算或加载。例如,缓存数据库查询结果。

5.案例代码

中国移动 - 代理商

在现实生活中,代理无处不在 - 代购、手机代理商、火车票代售点。。。

记得刚上大学时,去学校报道,基本上都要买手机(好怀念 Nokia)、办卡、充值。学校附近的各种代理点很多:"办卡、办卡,动感地带月租只要 18 啦"、"充值、充值,充 100 送 50"。。。各种吆喝声此起彼伏 O(∩_∩)O哈哈~,由于刚开学,代理点生意十分火爆,小顾客顾不上 - 低于 50 不充。

这里,代理模式可以理解为:移动公司把充值的职责托付给代理点,代理点代替移动公司充值,客户直接与代理点打交道,而非移动公司。

cpp 复制代码
#include <iostream>
using namespace std;

// Subject(接口),定义真实主题和代理都需要实现的方法
class MobileOperator {
public:
    virtual void recharge(int amount) = 0;
    virtual ~MobileOperator() {} // 虚析构函数,确保派生类的析构函数被调用
};

// RealSubject(真实主题),实现实际的充值逻辑
class ChinaMobile : public MobileOperator {
public:
    ChinaMobile() {
        cout << "中国移动:创建真实主题对象。" << endl;
    }
    
    ~ChinaMobile() {
        cout << "中国移动:销毁真实主题对象。" << endl;
    }
    
    void recharge(int amount) override {
        cout << "中国移动:充值 " << amount << " 元成功。" << endl;
    }
};

// Proxy(代理),控制对真实主题的访问
class MobileAgent : public MobileOperator {
private:
    ChinaMobile* realMobile; // 真实主题对象
public:
    MobileAgent() : realMobile(new ChinaMobile()) {
        cout << "代理商:创建代理对象。" << endl;
    }
    
    ~MobileAgent() {
        delete realMobile;
        cout << "代理商:销毁代理对象。" << endl;
    }
    
    void recharge(int amount) override {
        if (amount < 50) { // 代理商规定的最低充值金额
            cout << "代理商:充值金额低于 50 元,不接受充值。" << endl;
        } else {
            cout << "代理商:处理中..." << endl;
            realMobile->recharge(amount); // 委托真实主题处理
        }
    }
};

int main() {
    cout << "开始测试代理模式:" << endl;
    
    // 创建代理对象
    MobileAgent agent;
    
    // 测试不同充值金额的情况
    agent.recharge(30); // 应该提示金额低于 50 元
    agent.recharge(100); // 应该成功充值

    cout << "结束测试代理模式。" << endl;
    return 0;
}
相关推荐
雨中rain3 分钟前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
ALISHENGYA1 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
arong_xu1 小时前
现代C++锁介绍
c++·多线程·mutex
汤姆和杰瑞在瑞士吃糯米粑粑1 小时前
【C++学习篇】AVL树
开发语言·c++·学习
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
CodeClimb2 小时前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
奶香臭豆腐2 小时前
C++ —— 模板类具体化
开发语言·c++·学习
不想当程序猿_2 小时前
【蓝桥杯每日一题】分糖果——DFS
c++·算法·蓝桥杯·深度优先
cdut_suye3 小时前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
波音彬要多做3 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法