C++实现设计模式---代理模式 (Proxy)

代理模式 (Proxy)

代理模式 是一种结构型设计模式,它为其他对象提供一个代理以控制对该对象的访问。代理模式常用于延迟加载、访问控制、智能引用等场景。


意图

  • 提供对某对象的控制。
  • 控制对目标对象的访问,通常用于在不改变目标对象的情况下,附加额外的功能。
  • 常见于延迟加载、权限控制等场景。

使用场景

  1. 远程代理

    • 当对象存在于不同的地址空间时,代理模式提供了对远程对象的访问。
  2. 虚拟代理

    • 延迟对象的创建,只有在需要时才创建对象,避免不必要的资源消耗。
  3. 保护代理

    • 控制对某个对象的访问权限。代理对象负责控制访问。
  4. 智能代理

    • 对对象访问进行计数、缓存等操作。例如,记录访问次数、管理缓存等。

参与者角色

  1. 主题接口 (Subject)

    • 定义了目标对象和代理类的公共接口。
  2. 真实主题 (RealSubject)

    • 实现了 Subject 接口的目标对象,包含实际业务逻辑。
  3. 代理 (Proxy)

    • 代理类,持有真实主题对象的引用,代理请求到真实主题对象,附加控制逻辑。

示例代码

以下代码展示了如何使用代理模式控制对一个图片加载的访问。

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

// 主题接口
class Image {
public:
    virtual ~Image() = default;
    virtual void display() = 0; // 移除 const
};

// 真实主题:加载并显示图片
class RealImage : public Image {
private:
    std::string filename;

public:
    RealImage(const std::string& file) : filename(file) {
        loadImage();
    }

    void loadImage() const {
        std::cout << "Loading image: " << filename << std::endl;
    }

    void display() override {
        std::cout << "Displaying image: " << filename << std::endl;
    }
};

// 代理类:代理真实图片加载和显示
class ProxyImage : public Image {
private:
    RealImage* realImage;
    std::string filename;

public:
    ProxyImage(const std::string& file) : filename(file), realImage(nullptr) {}

    void display() override {
        if (!realImage) {
            realImage = new RealImage(filename);  // 延迟加载真实图像
        }
        realImage->display();
    }

    ~ProxyImage() {
        delete realImage;
    }
};

// 客户端代码
int main() {
    Image* image1 = new ProxyImage("image1.jpg");
    Image* image2 = new ProxyImage("image2.jpg");

    // 第一次访问时加载并显示图片
    image1->display();
    image2->display();

    // 直接显示图片,不会重新加载
    image1->display();

    delete image1;
    delete image2;

    return 0;
}

代码解析

1. 主题接口

  • Image 类定义了目标对象和代理类的公共接口。
  • 所有的图片类都需要实现 display 方法。
cpp 复制代码
class Image {
public:
    virtual ~Image() = default;
    virtual void display() = 0;
};

2. 真实主题

  • RealImage 类是实际的图片对象,提供了加载和显示图片的功能。
  • loadImage 在构造函数中被调用,用于模拟加载图片。
cpp 复制代码
class RealImage : public Image {
private:
    std::string filename;

public:
    RealImage(const std::string& file) : filename(file) {
        loadImage();
    }

    void loadImage() const {
        std::cout << "Loading image: " << filename << std::endl;
    }

    void display() override {
        std::cout << "Displaying image: " << filename << std::endl;
    }
};

3. 代理类

  • ProxyImage 类是一个代理类,它控制对 RealImage 的访问。
  • display 方法中,它会先检查 realImage 是否已被创建。如果尚未创建,则延迟加载它。
cpp 复制代码
class ProxyImage : public Image {
private:
    RealImage* realImage;
    std::string filename;

public:
    ProxyImage(const std::string& file) : filename(file), realImage(nullptr) {}

    void display() override {
        if (!realImage) {
            realImage = new RealImage(filename);  // 延迟加载真实图像
        }
        realImage->display();
    }

    ~ProxyImage() {
        delete realImage;
    }
};

4. 客户端

  • 客户端使用代理类,而不是直接使用真实主题类。
  • ProxyImage 控制了对 RealImage 的访问,并在必要时创建它。
cpp 复制代码
int main() {
    Image* image1 = new ProxyImage("image1.jpg");
    Image* image2 = new ProxyImage("image2.jpg");

    image1->display(); // 加载并显示
    image2->display(); // 加载并显示

    image1->display(); // 直接显示
    delete image1;
    delete image2;
}

优缺点

优点

  1. 延迟初始化

    • 代理模式可以在需要时才创建和初始化对象,避免不必要的资源消耗。
  2. 控制访问权限

    • 代理对象可以控制对真实对象的访问,如权限控制、延迟加载等。
  3. 增加功能而不改变目标对象

    • 通过代理,可以为目标对象添加附加功能,而无需修改目标对象。

缺点

  1. 增加系统复杂度

    • 代理模式增加了对象间的间接性,可能导致系统变得复杂。
  2. 性能开销

    • 使用代理时,可能会有额外的性能开销,特别是在频繁调用代理方法时。

适用场景

  1. 远程代理

    • 访问远程对象时,代理对象可以替代真实对象,并处理通信。
  2. 虚拟代理

    • 延迟对象的加载,当需要时才创建对象,避免不必要的资源消耗。
  3. 保护代理

    • 控制对真实对象的访问权限,确保只有符合条件的用户才能访问。

总结

代理模式通过提供一个替代的对象来控制对真实对象的访问。它广泛用于延迟加载、权限控制、远程调用等场景,能够有效提高系统的灵活性和可扩展性。

相关推荐
Yu_Lijing9 分钟前
基于C++的《Head First设计模式》笔记——工厂模式
c++·笔记·设计模式
十五年专注C++开发12 分钟前
CMake进阶:核心命令get_filename_component 完全详解
开发语言·c++·cmake·跨平台编译
mrcrack20 分钟前
洛谷 B3656 【模板】双端队列 1 方案1+离线处理+一维数组+偏移量 方案2+stl list
c++·list
lingzhilab21 分钟前
零知IDE——基于STMF103RBT6结合PAJ7620U2手势控制192位WS2812 RGB立方体矩阵
c++·stm32·矩阵
go_bai22 分钟前
生产消费模型-简洁线程池
linux·c++·笔记
mingren_131429 分钟前
c++和qml交互
c++·qt·交互
cn_mengbei33 分钟前
鸿蒙PC上Qt原生应用开发:从零搭建开发环境到部署实战,附HarmonyOS SDK配置与避坑指南(C++实现)
c++·qt·harmonyos
脏脏a36 分钟前
手撕 vector:从 0 到 1 模拟实现 STL 容器
开发语言·c++·vector
郝学胜-神的一滴40 分钟前
Linux 读写锁深度解析:原理、应用与性能优化
linux·服务器·c++·程序人生·性能优化
闻缺陷则喜何志丹1 小时前
【图论 DFS 换根法】3772. 子图的最大得分|2235
c++·算法·深度优先·力扣·图论·换根法