C++ Proxy Pattern怎么实现?代理模式在C++中怎么用?

文章导读
Previous Quiz Next Proxy 设计模式 是一种 结构型设计模式,它允许我们为另一个对象提供一个 替代品,或者说一个 占位符。在 Proxy 设计模式 中,一个 class 代表另一个 class 的功能。Proxy 接收客户端请求,执行一些工作(访问
📋 目录
  1. A Proxy 设计模式的类型
  2. B Proxy 设计模式的组件
  3. C C++ 中的代理设计模式实现
  4. D 代理设计模式的优缺点
  5. E 何时使用代理设计模式?
  6. F 代理设计模式在现实世界中的应用
  7. G 结论
A A

C++ 中的 Proxy 设计模式



Previous
Quiz
Next

Proxy 设计模式 是一种 结构型设计模式,它允许我们为另一个对象提供一个 替代品,或者说一个 占位符。在 Proxy 设计模式 中,一个 class 代表另一个 class 的功能。Proxy 接收客户端请求,执行一些工作(访问控制、缓存 等),然后将请求传递给 服务对象(原始对象)。

当我们需要为一个对象创建 包装器 来 控制对其的访问 时,就会使用 Proxy 设计模式。它还用于在不改变对象代码的情况下为其添加 额外功能。

考虑以下例子。在图片中,门卫为忙碌的 女王 与访客交谈。他传递消息并只允许合适的人进入——就像一个为她代言的 助手。这正是 proxy 所做的。

Proxy Design Pattern

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 创建一个代理,该代理模拟与数据库的连接。代理将控制对数据库的访问并添加缓存功能。

Database Proxy Example

实现代理设计模式的步骤

按照以下步骤在 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

代理设计模式的优缺点

使用代理设计模式的优点和缺点如下 −

优点 缺点
让你控制谁可以使用某物。 增加额外步骤,可能使事情变得更复杂。
你可以添加诸如保存结果或记录日志等功能,而无需更改主要对象。 由于代理的额外工作,可能会降低性能。
帮助你在真正需要时才创建对象。 由于需要检查更多内容,可能会使问题排查更困难。
通过检查使用权限来提高安全性。 并非总是需要,如果代理做太多工作可能会变得混乱。

何时使用代理设计模式?

以下是一些你可能想要使用代理设计模式的场景 −

  • 控制谁可以使用某物。
  • 添加保存结果或记录日志功能,而无需更改主要对象。
  • 延迟创建真实对象直到需要时。
  • 保护某物免受不应使用它的人的访问。
  • 管理某物的使用方式和时机。

代理设计模式在现实世界中的应用

以下是代理设计模式的一些现实世界应用 −

Real World Proxy Examples

结论

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