欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > C++设计模式:代理模式(Proxy)(附案例代码)

C++设计模式:代理模式(Proxy)(附案例代码)

2025/2/26 0:04:45 来源:https://blog.csdn.net/chenai886/article/details/144269460  浏览:    关键词:C++设计模式:代理模式(Proxy)(附案例代码)

什么是代理模式?

代理模式是一种结构型设计模式,主要用于为某个对象提供一个代理,以便在不直接访问对象的情况下控制对其的访问。代理可以在客户端和目标对象之间起到一个中介的作用,添加一些额外的操作,例如权限控制、性能优化(如延迟加载)、结果缓存、日志记录等。

通过代理模式,客户端与目标对象之间的耦合被降低,同时实现了对目标对象的透明化访问。


代理模式的特点

优点

  1. 控制对象访问

    • 可以通过代理控制对目标对象的访问,比如权限检查或延迟加载。
  2. 解耦增强系统灵活性

    • 客户端只需与代理对象交互,代理负责实际的操作逻辑,隐藏了具体的实现细节。
  3. 额外功能增强

    • 在不修改目标对象代码的前提下,通过代理扩展功能,例如添加日志记录、性能优化等。

缺点

  1. 增加系统复杂性

    • 引入代理对象会增加代码量和复杂性,尤其是代理逻辑较为复杂时。
  2. 性能开销

    • 代理本身需要额外的内存和处理时间。

代理模式的使用场景

  1. 权限控制(保护代理)

    • 根据用户角色或权限控制对目标对象的访问。
    • 例如:管理员可以查看银行账户余额,而普通用户不能。
  2. 延迟加载(虚拟代理)

    • 在需要时才创建目标对象。
    • 例如:大型资源(如图像、文件)在实际使用时再加载。
  3. 远程代理(Remote Proxy)

    • 为位于不同地址空间的对象提供本地代理。
    • 例如:远程方法调用(RMI)。
  4. 日志记录或审计

    • 在目标对象操作前后添加日志记录。
  5. 性能优化(缓存代理)

    • 缓存目标对象的操作结果,避免重复计算或网络请求。
  6. 智能引用(Smart Reference Proxy)

    • 在访问目标对象时进行计数、引用管理或预处理。

案例详解

以下通过两个案例详细解读代理模式:

  1. 虚拟代理(延迟加载)
  2. 保护代理(权限控制)

案例一:虚拟代理(延迟加载)

需求背景

假设我们要开发一个图片查看器应用。加载高清图片非常耗时,为了提升应用性能,我们可以使用代理模式,在需要时才加载图片。

代码实现
  1. 定义抽象接口

首先定义一个 Image 接口,供代理对象和目标对象实现。

#include <iostream>
#include <string>
#include <memory>
using namespace std;// 抽象图片接口
class Image {
public:virtual void display() = 0; // 定义显示图片的接口virtual ~Image() = default;
};

  1. 实现真实对象

RealImage 是需要加载的高清图片,它模拟了一个耗时的加载过程。

class RealImage : public Image {
private:string fileName;void loadFromDisk() {// 模拟加载图片cout << "Loading image: " << fileName << endl;}public:RealImage(const string& fileName) : fileName(fileName) {loadFromDisk(); // 在创建时加载图片}void display() override {cout << "Displaying image: " << fileName << endl;}
};

  1. 实现代理对象

ProxyImage 是虚拟代理,只有在需要显示图片时,才创建 RealImage

class ProxyImage : public Image {
private:string fileName;unique_ptr<RealImage> realImage; // 延迟加载的真实图片对象public:ProxyImage(const string& fileName) : fileName(fileName) {}void display() override {if (!realImage) {// 延迟加载真实图片realImage = make_unique<RealImage>(fileName);}realImage->display();}
};

  1. 客户端代码

客户端通过代理对象显示图片。

int main() {// 创建代理图片unique_ptr<Image> image = make_unique<ProxyImage>("test.jpg");// 第一次显示图片cout << "First time displaying image:" << endl;image->display();// 第二次显示图片cout << "Second time displaying image:" << endl;image->display();return 0;
}

运行结果
First time displaying image:
Loading image: test.jpg
Displaying image: test.jpg
Second time displaying image:
Displaying image: test.jpg
解读
  • 第一次显示时,ProxyImage 延迟加载了 RealImage,并执行加载操作。
  • 第二次显示时,直接使用已经加载好的图片,提升了性能。

案例二:保护代理(权限控制)

需求背景

实现一个银行账户系统,只有管理员用户可以查看账户余额,普通用户尝试查看时会被拒绝。

代码实现
  1. 定义接口

定义 BankAccount 接口,提供查看余额的功能。

class BankAccount {
public:virtual void showBalance() = 0; // 查看余额方法virtual ~BankAccount() = default;
};

  1. 实现真实对象

RealBankAccount 存储账户余额,并提供查看功能。

class RealBankAccount : public BankAccount {
private:double balance;public:RealBankAccount(double initialBalance) : balance(initialBalance) {}void showBalance() override {cout << "The balance is: $" << balance << endl;}
};

  1. 实现代理对象

BankAccountProxy 负责检查用户角色,只有管理员可以访问 RealBankAccount

class BankAccountProxy : public BankAccount {
private:unique_ptr<RealBankAccount> realAccount;string role; // 用户角色public:BankAccountProxy(double initialBalance, const string& userRole): realAccount(make_unique<RealBankAccount>(initialBalance)), role(userRole) {}void showBalance() override {if (role == "admin") {realAccount->showBalance();} else {cout << "Access denied: Only admin can view the balance." << endl;}}
};

  1. 客户端代码

客户端通过代理访问账户信息。

int main() {// 普通用户unique_ptr<BankAccount> userAccount = make_unique<BankAccountProxy>(1000.0, "user");userAccount->showBalance();// 管理员unique_ptr<BankAccount> adminAccount = make_unique<BankAccountProxy>(1000.0, "admin");adminAccount->showBalance();return 0;
}

运行结果
Access denied: Only admin can view the balance.
The balance is: $1000
解读
  • 普通用户尝试查看余额时,代理拒绝访问。
  • 管理员可以通过代理访问真实账户信息。

完整代码项目

文件结构
proxy_pattern_project/
│
├── main.cpp       // 主程序入口
├── Image.h        // 图片接口及相关类
├── BankAccount.h  // 银行账户接口及相关类

1. Image.h

// Image.h
#ifndef IMAGE_H
#define IMAGE_H#include <iostream>
#include <string>
#include <memory>
using namespace std;// 抽象图片接口
class Image {
public:virtual void display() = 0; // 定义显示图片的接口virtual ~Image() = default;
};// 真实图片类
class RealImage : public Image {
private:string fileName;void loadFromDisk() {// 模拟加载图片的过程cout << "加载图片:" << fileName << endl;}public:RealImage(const string& fileName) : fileName(fileName) {loadFromDisk(); // 构造时加载图片}void display() override {cout << "显示图片:" << fileName << endl;}
};// 代理图片类
class ProxyImage : public Image {
private:string fileName;unique_ptr<RealImage> realImage; // 延迟加载的真实图片对象public:ProxyImage(const string& fileName) : fileName(fileName) {}void display() override {if (!realImage) {// 延迟加载真实图片realImage = make_unique<RealImage>(fileName);}realImage->display();}
};#endif // IMAGE_H

2. BankAccount.h

// BankAccount.h
#ifndef BANK_ACCOUNT_H
#define BANK_ACCOUNT_H#include <iostream>
#include <memory>
#include <string>
using namespace std;// 抽象银行账户接口
class BankAccount {
public:virtual void showBalance() = 0; // 查看余额的方法virtual ~BankAccount() = default;
};// 真实银行账户类
class RealBankAccount : public BankAccount {
private:double balance;public:RealBankAccount(double initialBalance) : balance(initialBalance) {}void showBalance() override {cout << "账户余额:$" << balance << endl;}
};// 银行账户代理类
class BankAccountProxy : public BankAccount {
private:unique_ptr<RealBankAccount> realAccount;string role; // 用户角色public:BankAccountProxy(double initialBalance, const string& userRole): realAccount(make_unique<RealBankAccount>(initialBalance)), role(userRole) {}void showBalance() override {if (role == "admin") {realAccount->showBalance();} else {cout << "访问被拒绝:只有管理员可以查看余额。" << endl;}}
};#endif // BANK_ACCOUNT_H

3. main.cpp

// main.cpp
#include "Image.h"
#include "BankAccount.h"int main() {cout << "====== 虚拟代理示例(延迟加载图片) ======" << endl;// 创建代理图片对象unique_ptr<Image> image = make_unique<ProxyImage>("test.jpg");// 第一次显示图片(触发加载)cout << "第一次显示图片:" << endl;image->display();// 第二次显示图片(直接显示已加载的图片)cout << "第二次显示图片:" << endl;image->display();cout << "\n====== 保护代理示例(银行账户访问控制) ======" << endl;// 普通用户访问unique_ptr<BankAccount> userAccount = make_unique<BankAccountProxy>(1000.0, "user");cout << "普通用户尝试查看余额:" << endl;userAccount->showBalance();// 管理员访问unique_ptr<BankAccount> adminAccount = make_unique<BankAccountProxy>(1000.0, "admin");cout << "管理员查看余额:" << endl;adminAccount->showBalance();return 0;
}

示例输出

虚拟代理示例

====== 虚拟代理示例(延迟加载图片) ======
第一次显示图片:
加载图片:test.jpg
显示图片:test.jpg
第二次显示图片:
显示图片:test.jpg

保护代理示例

====== 保护代理示例(银行账户访问控制) ======
普通用户尝试查看余额:
访问被拒绝:只有管理员可以查看余额。
管理员查看余额:
账户余额:$1000

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词