代理模式的核心思路是引入一个代理类,代理类和被代理对象实现相同的接口,客户端通过代理类间接访问被代理对象,代理类可以在访问前后添加额外的控制逻辑,从而实现对被代理对象的访问管控。

代理模式的核心结构
代理模式通常包含三个核心角色:
- 抽象主题(Subject):定义被代理对象和代理类共同实现的接口,确保客户端可以无差别地使用代理类和被代理对象。
- 真实主题(RealSubject):实际处理业务逻辑的对象,也就是被代理的对象。
- 代理(Proxy):持有真实主题的引用,实现抽象主题接口,在客户端调用时控制对真实主题的访问,可在调用前后添加额外操作。
基础代理模式实现示例
以下以文件访问场景为例,实现权限控制的代理模式,只有拥有权限的用户才能访问文件内容。
1. 定义抽象主题接口
首先定义文件操作的抽象接口,包含读取文件的方法:
// 抽象主题:文件操作接口
class FileOperator {
public:
virtual ~FileOperator() = default;
// 读取文件内容的方法
virtual std::string readFile() = 0;
};
2. 实现真实主题类
真实主题类实现文件读取的实际逻辑:
// 真实主题:实际执行文件读取的类
class RealFileOperator : public FileOperator {
private:
std::string fileName;
public:
explicit RealFileOperator(std::string name) : fileName(std::move(name)) {}
std::string readFile() override {
// 模拟实际文件读取逻辑
return "文件" + fileName + "的内容:这是一段示例文本数据";
}
};
3. 实现代理类
代理类添加权限校验逻辑,只有校验通过才允许访问真实主题的方法:
// 代理类:控制文件访问权限
class FileProxy : public FileOperator {
private:
RealFileOperator* realOperator;
std::string userRole;
public:
FileProxy(std::string name, std::string role)
: realOperator(new RealFileOperator(std::move(name))), userRole(std::move(role)) {}
~FileProxy() override {
delete realOperator;
}
std::string readFile() override {
// 访问前校验权限
if (checkPermission()) {
// 权限通过,调用真实主题的方法
return realOperator->readFile();
} else {
return "权限不足,无法访问该文件";
}
}
private:
// 权限校验方法
bool checkPermission() {
// 模拟权限判断逻辑,admin角色有访问权限
return userRole == "admin";
}
};
4. 客户端调用示例
客户端通过代理类访问文件,无需直接操作真实主题对象:
#include <iostream>
#include <string>
int main() {
// 普通用户访问,权限不足
FileOperator* normalUserProxy = new FileProxy("测试文档.txt", "normal");
std::cout << normalUserProxy->readFile() << std::endl;
// 管理员用户访问,权限通过
FileOperator* adminProxy = new FileProxy("测试文档.txt", "admin");
std::cout << adminProxy->readFile() << std::endl;
delete normalUserProxy;
delete adminProxy;
return 0;
}
常见代理类型及适用场景
除了上述权限控制代理,C++中代理模式还有多种常见类型:
| 代理类型 | 作用 | 适用场景 |
|---|---|---|
| 虚拟代理 | 延迟真实对象的创建,直到真正需要时才初始化 | 加载大对象、大图片等资源时使用,避免启动时占用过多内存 |
| 远程代理 | 为远程对象提供本地代表,隐藏远程调用的细节 | 分布式系统、RPC调用场景,简化远程对象的使用逻辑 |
| 日志代理 | 在访问真实对象前后记录日志 | 需要监控对象调用情况、做操作审计的场景 |
实现注意事项
- 代理类和真实主题类必须实现相同的抽象接口,否则客户端无法无差别使用两者。
- 代理类的控制逻辑要尽量轻量,避免因为代理增加过多性能开销。
- 如果真实主题对象的生命周期由代理管理,要注意内存释放问题,避免内存泄漏。
- 不要在代理类中修改真实主题的核心业务逻辑,代理只负责访问控制和额外功能添加。
代理模式的核心价值是在不修改原有对象逻辑的前提下,扩展对象访问的控制能力,是解耦访问控制逻辑和业务逻辑的有效手段。