C++ 中的 Proxy 设计模式
Proxy 设计模式 是一种 结构型设计模式,它允许我们为另一个对象提供一个 替代品,或者说一个 占位符。在 Proxy 设计模式 中,一个 class 代表另一个 class 的功能。Proxy 接收客户端请求,执行一些工作(访问控制、缓存 等),然后将请求传递给 服务对象(原始对象)。
当我们需要为一个对象创建 包装器 来 控制对其的访问 时,就会使用 Proxy 设计模式。它还用于在不改变对象代码的情况下为其添加 额外功能。
考虑以下例子。在图片中,门卫为忙碌的 女王 与访客交谈。他传递消息并只允许合适的人进入——就像一个为她代言的 助手。这正是 proxy 所做的。
Proxy 设计模式的类型
以下是 Proxy 设计模式的各种类型 −
- Remote Proxy − 允许你使用位于 远处 的东西,可能在另一台计算机上。
- Virtual Proxy − 仅在实际需要时才创建 真实对象,从而节省 时间 和 内存。
- Protection Proxy − 在授予你 访问 之前检查你是否有权限使用某物。
- Caching Proxy − 存储 结果,如果再次请求相同内容,则快速返回。
- Logging Proxy − 记录使用 真实对象 时发生的事情。
- Synchronization Proxy − 确保任何时候只有 一个人 能使用某物,以避免 冲突。
- Smart Reference Proxy − 在使用某物时添加一些 额外步骤,如 计数 使用次数或仅在需要时 加载 它。
Proxy 设计模式的组件
- Subject − 真实对象和代理都使用的基本规则或操作。
- RealSubject − 执行主要工作的真实对象。
- Proxy − 为真实对象代言并控制谁可以使用它的代理。
C++ 中的代理设计模式实现
我们将在 C++ 中实现一个简单的代理设计模式示例。在这个示例中,我们将为 Database class 创建一个代理,该代理模拟与数据库的连接。代理将控制对数据库的访问并添加缓存功能。
实现代理设计模式的步骤
按照以下步骤在 C++ 中实现代理设计模式
- 定义 Subject 接口,该接口声明真实对象和代理的通用操作。
- 创建 RealSubject class,该 class 实现 Subject 接口并模拟数据库连接。
- 创建 Proxy class,该 class 也实现 Subject 接口并控制对 RealSubject 的访问。它将添加缓存功能。
- 在客户端代码中使用 Proxy class 来访问数据库。
代理设计模式的 C++ 代码
以下是演示代理设计模式的 C++ 代码 −
在这里,DatabaseProxy class 充当 RealDatabase class 的中间人。它保存第一次查询的结果,如果再次查询则返回保存的结果,展示了代理如何缓存数据。
#include <iostream>
#include <string>
using namespace std;
// Subject 接口
class Database {
public:
virtual string query(const string& sql) = 0;
virtual ~Database() {}
};
// RealSubject 类
class RealDatabase : public Database {
public:
string query(const string& sql) override {
// 模拟数据库查询
return "Results for query: " + sql;
}
};
// Proxy 类
class DatabaseProxy : public Database {
private:
RealDatabase* realDatabase;
string cachedResult;
bool isCached;
public:
DatabaseProxy() : realDatabase(nullptr), isCached(false) {}
string query(const string& sql) override {
if (!isCached) {
if (realDatabase == nullptr) {
realDatabase = new RealDatabase();
}
cachedResult = realDatabase->query(sql);
isCached = true;
} else {
cout << "Returning cached result." << std::endl;
}
return cachedResult;
}
~DatabaseProxy() {
delete realDatabase;
}
};
// 客户端代码
int main() {
Database* db = new DatabaseProxy();
// 第一次查询 - 将访问真实数据库
cout << db->query("SELECT * FROM users") << endl;
// 第二次查询 - 将返回缓存结果
cout << db->query("SELECT * FROM users") << endl;
delete db;
return 0;
}
以上代码的输出如下 −
Results for query: SELECT * FROM users Returning cached result. Results for query: SELECT * FROM users
代理设计模式的优缺点
使用代理设计模式的优点和缺点如下 −
| 优点 | 缺点 |
|---|---|
| 让你控制谁可以使用某物。 | 增加额外步骤,可能使事情变得更复杂。 |
| 你可以添加诸如保存结果或记录日志等功能,而无需更改主要对象。 | 由于代理的额外工作,可能会降低性能。 |
| 帮助你在真正需要时才创建对象。 | 由于需要检查更多内容,可能会使问题排查更困难。 |
| 通过检查使用权限来提高安全性。 | 并非总是需要,如果代理做太多工作可能会变得混乱。 |
何时使用代理设计模式?
以下是一些你可能想要使用代理设计模式的场景 −
- 控制谁可以使用某物。
- 添加保存结果或记录日志功能,而无需更改主要对象。
- 延迟创建真实对象直到需要时。
- 保护某物免受不应使用它的人的访问。
- 管理某物的使用方式和时机。
代理设计模式在现实世界中的应用
以下是代理设计模式的一些现实世界应用 −

结论
在本章中,你学习了什么是 Proxy Design Pattern,它是如何工作的,以及你可以在哪里使用它。Proxy 有助于你控制对某物的访问,并让你在不改变主要对象的情况下添加新功能。这是一种保持事物安全和有序的便捷方式。