C++设计模式之代理模式(Proxy)

C++设计模式之代理模式(Proxy)

代理模式是一种结构型设计模式,它允许将对象的访问控制在另一个对象中,从而在访问对象时提供间接的方式。代理模式允许我们通过使用另一个对象来代表实际的对象来控制对实际对象的访问。

适用场景

在以下情况下使用代理模式:

  • 当直接访问对象可能会危及对象的安全时。
  • 当访问一个对象需要很长时间时,因为每次访问都需要进行复杂的计算,而无需每次都计算。
  • 当需要在没有访问对象的基础上执行额外的操作时,例如对访问对象进行计数或访问日志。

实现方法

代理模式由两个角色组成:代理和实体。代理和实体都实现相同的接口。代理持有一个指向实体的引用,以及自身的属性。当客户端通过代理访问对象时,代理检查客户端是否有足够的权限,然后将调用传递给实体。

class Subject {
public:
  virtual void request() = 0;
};

class RealSubject : public Subject {
public:
  void request() override {
    std::cout << "RealSubject: Handling request.\n";
  }
};

class Proxy : public Subject {
private:
  RealSubject *real_subject_;

  bool check_access() const {
    std::cout << "Proxy: Checking access prior to firing a real request.\n";
    return true;
  }
  void log_access() const {
    std::cout << "Proxy: Logging the time of request.\n";
  }

public:
  Proxy(RealSubject *real_subject) : real_subject_(new RealSubject(*real_subject)) {
  }
  ~Proxy() {
    delete real_subject_;
  }

  void request() override {
    if (this->check_access()) {
      this->real_subject_->request();
      this->log_access();
    }
  }
};

上述代码演示了一个简单的代理模式。该代码包含三个类:Subject、RealSubject和Proxy。Subject类表示抽象接口,RealSubject类表示真实对象,Proxy类表示代理。实体和代理都遵循相同的接口。

Proxy类持有一个指向RealSubject对象的指针,并检查客户端是否有访问对象的权限。如果客户端具有访问权限,则代理将请求传递给RealSubject对象,并在代理中记录访问。

示例1:保护代理

代码演示了如何使用保护代理来控制对RealSubject对象的访问。

class RealSubject {
 public:
  void request() const {
    std::cout << "RealSubject: Handling request.\n";
  }
};

class Proxy {
 private:
  const RealSubject& real_subject_;

  bool check_access() const {
    // 一些复杂的验证逻辑。
    std::cout << "Proxy: Checking access prior to firing a real request.\n";
    return true;
  }

 public:
  Proxy(const RealSubject& real_subject) : real_subject_(real_subject) {}

  void request() const {
    if (this->check_access()) {
      this->real_subject_.request();
    }
  }
};

void client_code(const Proxy& proxy) {
  // ...

  proxy.request();

  // ...
}

int main() {
  RealSubject* real_subject = new RealSubject;
  Proxy* proxy = new Proxy(*real_subject);
  client_code(*proxy);
  delete real_subject;
  delete proxy;
  return 0;
}

示例2: 虚拟代理

代码演示了如何使用虚拟代理来延迟对RealSubject对象的创建和初始化。

class RealSubject {
 public:
  RealSubject() {
    std::cout << "RealSubject: Created.\n";
  }

  void request() const {
    std::cout << "RealSubject: Handling request.\n";
  }
};

class Proxy {
 private:
  RealSubject* real_subject_;

  bool check_access() const {
    // 一些复杂的验证逻辑。
    std::cout << "Proxy: Checking access prior to firing a real request.\n";
    return true;
  }

 public:
  Proxy() : real_subject_(nullptr) {}

  ~Proxy() {
    delete real_subject_;
  }

  void request() const {
    if (!real_subject_) {
      real_subject_ = new RealSubject;
    }
    if (this->check_access()) {
      this->real_subject_->request();
    }
  }
};

void client_code(const std::vector<Proxy*>& proxies) {
  // ...

  for (const Proxy* proxy : proxies) {
    proxy->request();
  }

  // ...
}

int main() {
  std::vector<Proxy*> proxies;
  proxies.push_back(new Proxy);
  client_code(proxies);

  for (const Proxy* proxy : proxies) {
    delete proxy;
  }
  return 0;
}

在上面的示例中,客户端执行了许多将请求传递给代理的操作。每次执行操作时,代理都必须检查访问权限并将请求转发给真实的主体对象。

此过程效率很低,因为在每个操作之间都要重复这些步骤。为了解决这个问题,可以使用虚拟代理。

使用虚拟代理时,真实主题对象将被延迟创建或初始化。虚拟代理只在必要时才会创建真实对象。在实际场景中,真实对象可能会在远程服务器上运行,或者可能非常大,需要很长时间才能初始化。在客户端等待真实对象初始化的过程中,代理可以做一些小的验证和验证操作。

总结

代理模式是一种结构型设计模式。它使代码更具模块性,并允许我们将对象的访问控制在另一个对象中。我们可以在代理中添加对客户端的额外检查和验证。在某些情况下,代理可以延迟对象的创建或初始化,以优化代码的性能和运行速度。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++设计模式之代理模式(Proxy) - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • 在ASP.NET 2.0中操作数据之三十八:处理BLL和DAL的异常

    在ASP.NET 2.0中操作数据之三十八:处理BLL和DAL的异常是一个重要的主题,对于开发者很有帮助。在开发应用程序时,处理异常是一个必要的过程,可以帮助我们检测和修复代码中的错误,提高程序的健壮性和可靠性。 异常处理的重要性 在应用程序开发中,异常处理非常重要。当应用程序发生异常,如果没有进行任何处理,程序将会停止运行,给用户带来极不好的使用体验。此时…

    C 2023年5月23日
    00
  • C程序 选择排序

    C程序 – 选择排序攻略 什么是选择排序? 选择排序是一种简单的排序算法。它的基本思想是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放到序列的起始位置,直到全部待排序的数据元素排完为止。 选择排序的过程 选择排序的过程可以通过以下步骤来描述: 从序列中选择最小/最大之一的元素; 把它与待排序的数组中的第一个元素交换位置; 从剩余的元素中继续选择…

    C 2023年5月9日
    00
  • C++中4种类型转换的方法分享

    当我们在C++编程中需要将一个数据类型转换为另一个数据类型时,可以使用以下四种类型转换方法: 1. 隐式类型转换 隐式类型转换(implicit conversion)是由编译器自动完成的类型转换,不需要程序员显式地调用转换函数或者使用强制类型转换运算符。例如,将整型变量赋给浮点型变量时,编译器会自动将整型变量转换为浮点型变量。示例代码如下: int i =…

    C 2023年5月30日
    00
  • C语言自动生成enum值和名字映射代码

    以下是详细讲解“C语言自动生成enum值和名字映射代码”的完整攻略: 背景 在C语言中,枚举类型(enum)是一个非常常用的数据类型。在实际的编程过程中,我们常常需要将枚举类型的变量转换成其对应的字符串表示或者将字符串表示转换成枚举类型的变量。手动编写这样的代码往往非常繁琐且容易出错,因此我们需要一种自动生成这样代码的工具。 工具 在这里,我们推荐使用开源工…

    C 2023年5月24日
    00
  • C语言之如何求三次方根

    C语言之如何求三次方根 在C语言中,求一个数的三次方根可以使用数学库中的pow()函数,但是这会增加程序的复杂度和开销。另一种方法是通过迭代逐步逼近三次方根的解,这种方法效率高,适合在不使用数学库的情况下求解三次方根。 方案原理 设正数n的三次方根为x,则有: $$ x^3 = n $$ 两边同时取平方根,得到: $$ x^2 = \sqrt{n} $$ 继…

    C 2023年5月23日
    00
  • Swift如何调用Objective-C的可变参数函数详解

    那么首先我们需要了解的是Objective-C中的可变参数函数的使用方式和Swift对其的调用方式。 在Objective-C中,可变参数函数通常使用va_list和va_start、va_arg、va_end等宏来进行参数的处理。其中 va_start宏接受可变参数函数的参数列表以及可变参数的最后一个非变长参数,在获取可变参数时,需要使用 va_arg宏进…

    C 2023年5月23日
    00
  • 详解C++异常处理(try catch throw)完全攻略

    作为本站的作者,我非常乐意为你介绍“详解C++异常处理(try-catch-throw)完全攻略”的内容。本篇攻略将涵盖以下主题,包括异常的概念,异常处理基本原则,以及如何使用try-catch块和throw语句等。 异常的概念 在C++程序中,如果发生了意外的错误,比如说磁盘空间不足,用户输入错误的数据等,这些都不是我们程序的预期结果。这时,程序会抛出一个…

    C 2023年5月22日
    00
  • C语言 continue语句

    当C语言程序执行到循环体内部时,某些情况下需要跳过当前循环,立即进入下一次循环,或者直接跳出循环继续执行下面的代码,这时可以使用continue语句来实现。 continue语句的使用方法如下: for (初始化; 条件表达式; 计数器更新) { if (满足条件) { continue; } // 循环体语句 } 当循环中满足某个条件时,continue语…

    C 2023年5月9日
    00
合作推广
合作推广
分享本页
返回顶部