跳转到内容

C++ 代理模式

来自代码酷

C++代理模式[编辑 | 编辑源代码]

介绍[编辑 | 编辑源代码]

代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理模式的主要目的是在不改变原始对象(或称为“真实对象”)的情况下,通过引入代理对象来间接访问目标对象,从而实现对目标对象的控制或增强功能。

代理模式通常用于以下场景:

  • 远程代理:为位于不同地址空间的对象提供本地代表(例如远程方法调用RMI)。
  • 虚拟代理:根据需要创建开销较大的对象(例如延迟加载)。
  • 保护代理:控制对原始对象的访问权限。
  • 智能引用:在访问对象时执行额外的操作(例如引用计数、日志记录等)。

代理模式的类型[编辑 | 编辑源代码]

在C++中,代理模式通常可以分为以下几种类型: 1. 静态代理:在编译时确定代理类和被代理类的关系。 2. 动态代理:在运行时动态生成代理类(C++中通常需要使用第三方库或元编程技术实现)。

实现示例[编辑 | 编辑源代码]

以下是一个静态代理的示例,展示如何使用代理模式控制对真实对象的访问:

#include <iostream>
#include <string>

// 抽象主题接口
class Subject {
public:
    virtual void request() const = 0;
    virtual ~Subject() = default;
};

// 真实主题
class RealSubject : public Subject {
public:
    void request() const override {
        std::cout << "RealSubject: Handling request.\n";
    }
};

// 代理类
class Proxy : public Subject {
private:
    RealSubject* real_subject_;

    bool checkAccess() const {
        std::cout << "Proxy: Checking access prior to firing a real request.\n";
        return true;
    }

    void logAccess() const {
        std::cout << "Proxy: Logging the time of request.\n";
    }

public:
    Proxy(RealSubject* real_subject) : real_subject_(new RealSubject(*real_subject)) {}

    ~Proxy() {
        delete real_subject_;
    }

    void request() const override {
        if (this->checkAccess()) {
            this->real_subject_->request();
            this->logAccess();
        }
    }
};

// 客户端代码
void ClientCode(const Subject& subject) {
    subject.request();
}

int main() {
    std::cout << "Client: Executing the client code with a real subject:\n";
    RealSubject* real_subject = new RealSubject;
    ClientCode(*real_subject);
    std::cout << "\n";

    std::cout << "Client: Executing the same client code with a proxy:\n";
    Proxy* proxy = new Proxy(real_subject);
    ClientCode(*proxy);

    delete real_subject;
    delete proxy;
    return 0;
}

输出结果:

Client: Executing the client code with a real subject:
RealSubject: Handling request.

Client: Executing the same client code with a proxy:
Proxy: Checking access prior to firing a real request.
RealSubject: Handling request.
Proxy: Logging the time of request.

类图[编辑 | 编辑源代码]

以下是代理模式的类图表示:

classDiagram class Subject { <<interface>> +request()* } class RealSubject { +request() } class Proxy { -real_subject: RealSubject +request() -checkAccess() bool -logAccess() } Subject <|-- RealSubject Subject <|-- Proxy Proxy o-- RealSubject

实际应用案例[编辑 | 编辑源代码]

代理模式在实际开发中有许多应用场景:

1. 延迟加载(Lazy Loading)

  在大型对象或资源密集型对象的场景中,可以使用代理模式实现延迟加载,只有当真正需要时才创建对象。

2. 访问控制

  代理可以检查调用者是否有权限执行特定操作,例如在数据库访问层实现权限控制。

3. 日志记录

  代理可以在调用真实对象的方法前后添加日志记录功能,而不需要修改原始类。

4. 远程服务调用

  当客户端需要访问远程服务时,可以使用代理模式在本地创建一个远程服务的代理,隐藏网络通信的复杂性。

优缺点[编辑 | 编辑源代码]

优点[编辑 | 编辑源代码]

  • 可以在不修改真实对象的情况下控制对对象的访问
  • 代理可以充当客户端和真实对象之间的中介,提供额外的功能
  • 开闭原则:可以在不修改客户端代码的情况下引入新的代理
  • 单一职责原则:可以将管理特定功能的代码分离到代理中

缺点[编辑 | 编辑源代码]

  • 由于引入了额外的代理层,可能会增加系统的复杂性
  • 代理调用可能会增加响应时间(特别是在远程代理的情况下)
  • 静态代理需要为每个服务类创建代理类,可能导致类数量增加

高级主题[编辑 | 编辑源代码]

对于更高级的C++开发者,可以考虑以下扩展主题:

1. 使用模板实现通用代理

  可以使用C++模板技术创建通用的代理类,减少重复代码。
template <typename T>
class GenericProxy {
    T* real_object_;
public:
    GenericProxy(T* real_obj) : real_object_(real_obj) {}
    
    T* operator->() const {
        // 可以在这里添加预处理逻辑
        return real_object_;
    }
    
    // 其他代理方法...
};

2. 使用std::function实现动态代理

  现代C++可以使用std::function和lambda表达式实现更灵活的代理机制。

3. 使用第三方库实现动态代理

  如Boost.Python或各种AOP(面向切面编程)库可以实现更强大的代理功能。

总结[编辑 | 编辑源代码]

代理模式是C++中一种非常有用的设计模式,它通过引入代理对象来控制对真实对象的访问。这种模式在需要添加额外控制层或功能增强时特别有用,同时保持客户端代码不变。理解并掌握代理模式可以帮助开发者编写更灵活、更可维护的代码。