设计模式十三:代理模式(Proxy Pattern)

代理模式是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。

代理模式的主要角色

  1. Subject(抽象主题):定义真实主题和代理主题的共同接口

  2. RealSubject(真实主题):实现真正的业务逻辑

  3. Proxy(代理):包含对真实主题的引用,可以控制对真实主题的访问

代理模式的类型

  1. 虚拟代理:延迟创建开销大的对象

  2. 远程代理:为远程对象提供本地代表

  3. 保护代理:控制对原始对象的访问权限

  4. 智能引用代理:在访问对象时执行附加操作(如引用计数)

代码示例

复制代码
#include <iostream>
#include <memory>
#include <string>

// 抽象主题
class Image {
public:
    virtual ~Image() = default;
    virtual void display() = 0;
};

// 真实主题
class RealImage : public Image {
public:
    RealImage(const std::string& filename) : filename(filename) {
        loadFromDisk();
    }
    
    void display() override {
        std::cout << "Displaying " << filename << std::endl;
    }
    
private:
    void loadFromDisk() {
        std::cout << "Loading " << filename << " from disk" << std::endl;
    }
    
    std::string filename;
};

// 代理
class ProxyImage : public Image {
public:
    ProxyImage(const std::string& filename) : filename(filename), realImage(nullptr) {}
    
    void display() override {
        if (realImage == nullptr) {
            realImage = std::make_unique<RealImage>(filename);
        }
        realImage->display();
    }
    
private:
    std::string filename;
    std::unique_ptr<RealImage> realImage;
};

// 使用示例
int main() {
    ProxyImage image1("photo1.jpg");
    ProxyImage image2("photo2.jpg");
    
    // 图像第一次显示时会从磁盘加载
    image1.display();
    
    // 图像已经加载过,直接从内存显示
    image1.display();
    
    // 另一个图像第一次显示
    image2.display();
    
    return 0;
}

UML结构

要点总结

1、"增加一层间接层"是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。

2、具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy。

3、Proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。

代理模式的优点

  1. 可以控制对真实对象的访问

  2. 作为真实对象和客户端之间的中介,可以增加额外的功能

  3. 可以延迟真实对象的创建和初始化

  4. 可以实现远程访问

代理模式的缺点

  1. 可能会引入额外的复杂度

  2. 可能会增加响应时间(因为多了一层代理)

适用场景

  1. 需要延迟加载(Lazy Initialization)时

  2. 需要控制对原始对象的访问权限时

  3. 需要为远程对象提供本地接口时

  4. 需要为对象访问添加日志或监控时