设计模式-04 设计模式-Proxy Pattern 代理模式

发布于:2024-05-07 ⋅ 阅读:(23) ⋅ 点赞:(0)
设计模式-04 设计模式-Proxy Pattern 代理模式
 

1.定义

代理模式 为一个对象提供一个代理或占位符,以便控制对该对象的访问和操作。代理可以拦截并修改对目标对象的调用,从而实现以下目的:

控制访问:限制对敏感或昂贵对象的访问,只允许经过身份验证或授权的用户访问。
延迟实例化:推迟创建昂贵或耗时的对象,直到真正需要时才创建。
提供额外的功能(日志记录,监控):在不修改目标对象的情况下,向目标对象添加额外的功能,例如日志记录、缓存或安全检查。
缓存功能:对于昂贵的对象,可以减少重复创建,减少调用真实对象的次数

       


          +--------------+
          |              |
          |   Interface  |
          |              |
          +--------------+
                 |
                 v
          +--------------+            +--------------+
          |   Proxy       |  ----|>   |   Concrete   |
          |   Object      |           |  Object      |
          +--------------+            +--------------+
2.内涵

代理模式 结构,代理模式包含以下角色:

  • Subject(目标):被代理的真实对象。
  • Proxy(代理):提供对目标对象的代理或占位符。
  • Client(客户端):使用代理来访问目标对象。

常用例子:

一个代理模式的例子是远程代理,它可以代表远程服务器上的对象。远程代理拦截对本地对象的调用,并将其转发到远程服务器上的实际对象。这允许客户端与远程对象交互,而无需直接访问远程服务器。

此外开源软件里面用的此模式的场景:

  • Mockito:使用代理模式创建模拟对象,用于单元测试。
  • Javassist:使用代理模式动态生成字节码,用于增强和修改现有类。
  • ASM:使用代理模式在字节码级别增强和修改类。
3.案例

一个简单使用 代理模式的c++ demo 

#include <iostream>
 
using namespace std;
 
class Image {
public:
    virtual void display() = 0;
};
 
class RealImage : public Image {
private:
    std::string filename;
 
public:
    RealImage(const std::string& filename) : filename(filename) {
        std::cout << "加载 image: " << filename << std::endl;
    }
 
    void display() override {
        std::cout << "显示 image: " << filename << std::endl;
    }
};


class ImageProxy : public Image {
private:
    RealImage* realImage;
    std::string filename;
 
public:
    ImageProxy(const std::string& filename) : filename(filename), realImage(nullptr) {}
 
    void display() override {
        if (nullptr == realImage) {
            realImage = new RealImage(filename);  // 如果有加载这次就不加载
        }
        realImage->display();
    }
};
 
 
int main() {
    Image* image = new ImageProxy("example.jpg");
    image->display(); // 具有缓存功能
    image->display();
    delete image; // Clean up
    return 0;
}
4.最佳实践


代理模式最佳实践:

明确代理目的:清楚地定义代理的职责和它要解决的问题。
将代理与目标对象解耦:代理不应该直接依赖于目标对象的具体实现。使用抽象接口或基类来表示目标对象,以便代理可以与不同的目标对象一起使用。
保持代理与目标对象同步:如果目标对象的状态发生变化,代理也应该相应地更新。
避免代理循环:确保代理不会直接或间接地引用自身,否则会导致无限循环。
使用虚拟代理来延迟实例化:只在需要时才创建目标对象,以提高性能。
考虑使用 AOP(面向方面编程):AOP 框架可以简化代理的创建和管理,尤其是在需要向多个对象添加类似功能的情况下。
谨慎使用代理:过度使用代理可能会降低性能并增加代码复杂性。只在真正需要的时候使用代理。
测试代理:编写测试以验证代理的正确行为,包括边界条件和异常情况。

此外以下也需要重点关注:

使用设计模式来增强代理:例如,可以使用工厂模式来创建代理,或者使用单例模式来确保只有一个代理实例。
考虑使用库或框架来实现代理:有许多库和框架(如 Spring AOP)提供开箱即用的代理实现。
记录代理的用途和限制:在代码中清楚地记录为什么使用代理以及代理的限制。


5.总结

代理模式在 C++中的应用是一种有价值的工具,可以增强应用程序的控制力和效率。通过使用代理,可以实现延迟初始化、访问控制、日志记录和缓存,从而提高代码的性能和可维护性。它允许你在不改变类结构的情况下为类添加额外的功能层。在恰当应用时,代理模式可以成为你设计模式工具箱中的一个强有力武器。