跳转到内容

C++ 代理模式实现

来自代码酷
Admin留言 | 贡献2025年4月28日 (一) 21:29的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)


代理模式(Proxy Pattern)是设计模式中的一种结构型模式,它通过提供一个代理对象来控制对另一个对象的访问。代理模式常用于延迟初始化、访问控制、日志记录等场景。在C++中,代理模式通常通过接口继承和组合来实现。

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

代理模式的核心思想是为其他对象提供一种代理,以控制对这个对象的访问。代理对象可以在客户端和目标对象之间起到中介的作用,从而在不修改目标对象代码的情况下增加额外的功能。

代理模式的主要角色包括:

  • Subject(抽象主题):定义真实主题和代理主题的共同接口。
  • RealSubject(真实主题):实现抽象主题的具体业务逻辑。
  • Proxy(代理):持有对真实主题的引用,控制对真实主题的访问。

实现方式[编辑 | 编辑源代码]

以下是代理模式在C++中的典型实现方式:

1. 静态代理[编辑 | 编辑源代码]

静态代理在编译时就已经确定代理关系。

#include <iostream>
#include <string>

// 抽象主题
class Image {
public:
    virtual void display() = 0;
    virtual ~Image() = default;
};

// 真实主题
class RealImage : public Image {
public:
    RealImage(const std::string& filename) : filename_(filename) {
        loadFromDisk();
    }

    void display() override {
        std::cout << "Displaying " << filename_ << std::endl;
    }

private:
    void loadFromDisk() {
        std::cout << "Loading " << filename_ << " from disk" << std::endl;
    }

    std::string filename_;
};

// 代理
class ProxyImage : public Image {
public:
    ProxyImage(const std::string& filename) : filename_(filename), realImage_(nullptr) {}

    void display() override {
        if (realImage_ == nullptr) {
            realImage_ = new RealImage(filename_);
        }
        realImage_->display();
    }

    ~ProxyImage() {
        delete realImage_;
    }

private:
    std::string filename_;
    RealImage* realImage_;
};

// 客户端代码
int main() {
    Image* image = new ProxyImage("test.jpg");
    
    // 第一次访问会加载图片
    image->display();
    
    // 第二次访问直接显示图片
    image->display();
    
    delete image;
    return 0;
}

输出结果:

Loading test.jpg from disk
Displaying test.jpg
Displaying test.jpg

2. 动态代理[编辑 | 编辑源代码]

C++本身不直接支持动态代理(如Java的Proxy类),但可以通过模板和运行时多态实现类似效果。

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

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

classDiagram class Image { <<interface>> +display() void } class RealImage { -filename: string +RealImage(filename: string) +display() void -loadFromDisk() void } class ProxyImage { -filename: string -realImage: RealImage* +ProxyImage(filename: string) +display() void } Image <|-- RealImage Image <|-- ProxyImage ProxyImage o-- RealImage

应用场景[编辑 | 编辑源代码]

代理模式在以下场景中特别有用:

1. 虚拟代理:延迟创建开销大的对象(如图片加载)。 2. 保护代理:控制对原始对象的访问权限。 3. 远程代理:为位于不同地址空间的对象提供本地代表。 4. 智能引用:在访问对象时执行额外操作(如引用计数、锁检查)。

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

考虑一个银行账户系统,我们可能希望添加访问控制:

#include <iostream>
#include <string>

class BankAccount {
public:
    virtual void withdraw(int amount) = 0;
    virtual ~BankAccount() = default;
};

class RealBankAccount : public BankAccount {
public:
    void withdraw(int amount) override {
        std::cout << "Withdrew $" << amount << " from account" << std::endl;
    }
};

class SecureBankAccountProxy : public BankAccount {
public:
    SecureBankAccountProxy(const std::string& user) : user_(user), realAccount_(nullptr) {}

    void withdraw(int amount) override {
        if (checkAccess()) {
            if (realAccount_ == nullptr) {
                realAccount_ = new RealBankAccount();
            }
            realAccount_->withdraw(amount);
        } else {
            std::cout << "Access denied for user: " << user_ << std::endl;
        }
    }

    ~SecureBankAccountProxy() {
        delete realAccount_;
    }

private:
    bool checkAccess() {
        // 简单的权限检查
        return user_ == "admin";
    }

    std::string user_;
    RealBankAccount* realAccount_;
};

int main() {
    BankAccount* adminAccount = new SecureBankAccountProxy("admin");
    BankAccount* userAccount = new SecureBankAccountProxy("user");
    
    adminAccount->withdraw(100);  // 允许
    userAccount->withdraw(50);    // 拒绝
    
    delete adminAccount;
    delete userAccount;
    return 0;
}

输出结果:

Withdrew $100 from account
Access denied for user: user

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

优点:

  • 可以在不修改目标对象的情况下增加功能
  • 职责清晰,符合单一职责原则
  • 可以实现对象的延迟加载
  • 可以控制对目标对象的访问

缺点:

  • 可能会增加系统的复杂度
  • 在客户端和目标对象之间增加了代理层,可能会影响性能

与其他模式的关系[编辑 | 编辑源代码]

  • 适配器模式:改变被适配对象的接口,而代理模式保持相同的接口。
  • 装饰器模式:增强对象的功能,而代理模式控制对对象的访问。
  • 外观模式:为一组接口提供统一接口,而代理模式为单个对象提供替代接口。

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

代理模式是C++中一种非常有用的设计模式,它通过引入代理对象来控制对原始对象的访问。这种模式特别适用于需要控制对象访问、延迟加载或添加额外功能的场景。理解并掌握代理模式可以帮助开发者编写更加灵活和可维护的代码。