代理模式(附C++代码示例)

代理模式的含义

代理模式(Proxy Pattern)是一种结构型设计模式,它通过提供一个代理或占位符对象来控制对另一个对象的访问。这种模式创建了一个具有原始对象相同接口的对象,使得代理可以在客户端和目标对象之间起到中介的作用,控制或增强对这个目标对象的访问。

核心思想及解释

代理模式的核心思想是控制对象访问,即通过代理对象间接访问目标对象。代理可以在不改变目标对象代码的前提下,进行一些前/后处理,或者在某些情况下不直接访问对象,而是通过一个代理来实现功能,这可以增加额外的功能,如安全性检查、延迟初始化、网络连接、记录日志等。

为什么要使用代理模式

  1. 控制访问:使用代理模式可以控制对特定对象的访问,实现权限控制、延迟初始化等。
  2. 增加功能:在不修改目标对象的情况下增加额外的功能。
  3. 简化网络操作:可以将网络操作的复杂性封装在代理中,使得客户端操作更为简单。

使用代理模式需要注意的点

  1. 可能导致系统变慢:因为增加了额外的层次和处理,可能会导致系统响应时间增加。
  2. 增加系统复杂性:引入代理模式可能会使系统设计更复杂,需要维护额外的代理类。
  3. 透明性问题:虽然代理提供了与目标对象相同的接口,但客户端可能需要了解是否是通过代理来访问对象。

工程的应用场景

  1. 远程代理:为一个对象在不同的地址空间提供局部代表。
  2. 虚拟代理:根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象。
  3. 保护代理:控制对原始对象的访问权限,用于对象应有的权限管理。

示例代码及解释–虚拟代理

假设有一个文档编辑器需要加载和显示图像,图像的加载可能很耗时。我们可以使用虚拟代理来延迟图像的加载过程,只有在实际需要显示图像时才进行加载。

首先,定义图像显示的接口和真实图像类:

#include <iostream>
#include <thread>
#include <chrono>

using namespace std;

// 抽象接口
class Image {
public:
    virtual void display() = 0;
    virtual ~Image() {}
};

// 真实图像类
class RealImage : public Image {
    string filename;
public:
    RealImage(const string& filename) : filename(filename) {
        loadFromDisk();
    }
    void display() override {
        cout << "Displaying " << filename << endl;
    }
    void loadFromDisk() {
        cout << "Loading " << filename << endl;
        this_thread::sleep_for(chrono::seconds(2)); // 模拟耗时加载
    }
};

定义代理类:

// 代理类
class ProxyImage : public Image {
    RealImage* realImage;
    string filename;
public:
    ProxyImage(const string& filename) : realImage(nullptr), filename(filename) {}
    ~ProxyImage() {
        delete realImage;
    }
    void display() override {
        if (!realImage) {
            realImage = new RealImage(filename); // 延迟初始化
        }
        realImage->display();
    }
};

客户端代码:

int main() {
    Image* image = new ProxyImage("test_10mb.jpg");
    // 图像不会在此时加载
    cout << "Image will be displayed

 now:\n";
    image->display(); // 图像在需要时才被加载和显示
    delete image;
    return 0;
}

输出代码运行结果–虚拟代理

Image will be displayed now:
Loading test_10mb.jpg
Displaying test_10mb.jpg

这个示例展示了如何使用虚拟代理模式来优化资源的加载过程。ProxyImage 代理类负责代表 RealImage,并在实际需要时(即调用 display 方法时)才加载图像,这样可以减少程序启动时的加载时间,特别是对于资源密集型操作非常有用。

示例代码及解释–保护代理

考虑一个简单的情况:我们有一个文档编辑器,其中文档可能包含敏感信息。我们希望只有拥有适当访问权限的用户可以打开或修改这些文档。

我们首先定义一个文档的接口和一个实现该接口的具体类,然后通过保护代理来控制对这个类的访问。

#include <iostream>
#include <string>

using namespace std;

// 文档接口
class Document {
public:
    virtual void open() = 0;
    virtual void save() = 0;
    virtual ~Document() {}
};

// 真实文档类
class RealDocument : public Document {
    string content;
public:
    RealDocument(const string& content) : content(content) {}
    void open() override {
        cout << "Document Content: " << content << endl;
    }
    void save() override {
        cout << "Saving document..." << endl;
    }
};

接下来,我们定义一个保护代理类,它将检查用户的访问权限:

// 保护代理
class ProtectedDocumentProxy : public Document {
    RealDocument* realDocument;
    string userRole;
public:
    ProtectedDocumentProxy(const string& content, const string& userRole)
        : realDocument(new RealDocument(content)), userRole(userRole) {}
    ~ProtectedDocumentProxy() {
        delete realDocument;
    }

    void open() override {
        if (userRole == "admin" || userRole == "editor") {
            realDocument->open();
        } else {
            cout << "Access Denied. You do not have permission to open this document." << endl;
        }
    }

    void save() override {
        if (userRole == "admin") {
            realDocument->save();
        } else {
            cout << "Access Denied. You do not have permission to save this document." << endl;
        }
    }
};

在客户端代码中,我们将模拟不同用户角色尝试访问文档的情况:

int main() {
    Document* doc1 = new ProtectedDocumentProxy("Confidential - Top Secret", "editor");
    Document* doc2 = new ProtectedDocumentProxy("General Information", "viewer");

    cout << "User with 'editor' role trying to open and save the first document:\n";
    doc1->open();
    doc1->save();

    cout << "\nUser with 'viewer' role trying to open and save the second document:\n";
    doc2->open();
    doc2->save();

    delete doc1;
    delete doc2;

    return 0;
}

输出代码运行结果–保护代理

User with 'editor' role trying to open and save the first document:
Document Content: Confidential - Top Secret
Access Denied. You do not have permission to save this document.

User with 'viewer' role trying to open and save the second document:
Access Denied. You do not have permission to open this document.
Access Denied. You do not have permission to save this document.

这个例子演示了如何使用保护代理来实现对敏感文档的访问控制。代理根据用户的角色(如管理员、编辑者、查看者)决定是否允许执行打开或保存操作,从而保护文档不被未授权的访问或修改。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Warren++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值