设计模式--代理模式(Proxy Pattern)

news2024/10/6 10:28:22

一、什么是代理模式(Proxy Pattern)

代理模式(Proxy Pattern)是一种结构型设计模式,它允许一个对象(代理)充当另一个对象(真实对象)的接口,以控制对该对象的访问。代理对象可以在访问真实对象之前或之后执行一些操作,从而增强或限制真实对象的行为。

代理模式的主要目的是为了控制访问,而不是简单地添加功能。它可以用于实现以下目标:

  1. 代理模式的主要目的是为了控制访问,而不是简单地添加功能。它可以用于实现以下目标:
  2. 虚拟代理: 代理对象在需要时才实例化真实对象。这可以用于减少启动时间,或者对于昂贵的对象,可以延迟其创建。
  3. 保护代理: 代理对象控制对真实对象的访问,可以添加权限控制或访问限制。
  4. 缓存代理: 代理对象可以缓存真实对象的信息,以便在后续访问中提高性能。
  5. 日志记录代理: 代理对象可以记录对真实对象的操作,以进行日志记录、性能监测等。

在代理模式中,通常有以下角色:

  1. 抽象主题(Subject): 定义了真实对象和代理对象的共同接口,以确保代理对象可以替代真实对象。
  2. 真实主题(Real Subject): 实际的业务对象,是代理所代表的对象,具有真正的功能。
  3. 代理(Proxy): 提供与真实对象相同的接口,可以对真实对象的访问进行控制和管理。

代理模式的优势包括:

  • 控制对真实对象的访问,从而可以进行权限控制、延迟加载等操作。
  • 提供额外的功能,如日志记录、缓存等,而不需要修改真实对象。

然而,代理模式也可能引入了复杂性,因为需要创建额外的代理类。在使用代理模式时,需要根据情况权衡代理的好处和代理类的数量。

二、代理模式的一个现实应用场景

一个现实的应用场景,可以通过一个虚拟代理的例子来解释代理模式。

场景:虚拟图片加载器

假设你正在开发一个图片浏览器应用,其中用户可以浏览并查看大量的高分辨率图片。然而,由于这些图片可能非常大,加载它们可能需要一些时间,特别是在网络较慢的情况下。为了提高用户体验并减少加载时间,你可以使用代理模式来实现一个虚拟图片加载器。

在这个场景中,有以下几个角色:

  1. 抽象主题(Image): 定义了图片的共同接口,可以是真实图片和代理图片的共同基类。
  2. 真实主题(RealImage): 实际的高分辨率图片对象,具有加载和显示的功能。
  3. 代理(ProxyImage): 代理图片对象,具有与真实图片相同的接口,但它并不立即加载真实图片,而是在需要时才加载。此外,代理还可以在加载前显示一些低分辨率的缩略图。

在这个场景中,代理模式的好处显而易见:

  • 用户在查看图片时,不需要等待图片加载完成,而是先显示缩略图,从而提高了用户体验。
  • 只有在用户真正需要查看大图时,才会进行真正的图片加载,从而减少了不必要的加载时间和网络资源消耗。

总之,代理模式在这个应用场景中通过虚拟图片加载器的实现,提供了一种有效的方式来控制和优化图片的加载和显示,从而提高了用户体验。

三、代理模式的代码样例

下面是一个使用 C++ 实现代理模式的简单示例,以虚拟图片加载器为例:

#include <iostream>

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

// 真实主题
class RealImage : public Image {
private:
    std::string filename;

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

    void loadImageFromDisk() {
        std::cout << "Loading image from disk: " << 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& filename) : filename(filename), realImage(nullptr) {}

    void display() override {
        if (!realImage) {
            realImage = new RealImage(filename);
        }
        realImage->display();
    }

    ~ProxyImage() {
        if (realImage) {
            delete realImage;
        }
    }
};

int main() {
    Image* image1 = new ProxyImage("image1.jpg");
    Image* image2 = new ProxyImage("image2.jpg");

    image1->display();  // 实际图片会被加载和显示
    image2->display();  // 实际图片会被加载和显示

    delete image1;
    delete image2;

    return 0;
}

在这个示例中,我们定义了一个抽象主题 Image,一个真实主题 RealImage 用于加载和显示实际图片,以及一个代理 ProxyImage 用于延迟加载真实图片,并在需要时显示。在 main 函数中,我们通过代理对象加载和显示图片。

这个示例演示了代理模式的概念,代理对象可以控制和管理对真实对象的访问。

四、使用代理模式需要注意的问题

在使用代理模式时,需要注意以下几个问题:

  1. 性能问题: 虽然代理模式可以在某些情况下提高性能(例如延迟加载),但代理本身可能会引入一定的开销,特别是在代理对象需要频繁创建和销毁时。需要权衡代理的好处和性能影响。
  2. 代理的数量: 过多的代理对象可能会导致类的数量增加,增加代码的复杂性。在选择使用代理模式时,需要考虑代理的数量是否合理,以避免引入过多的类。
  3. 代理的一致性: 代理对象需要和真实对象具有一致的接口,以便可以无缝替换。确保代理对象的接口与真实对象保持一致,从而避免类型不匹配的问题。
  4. 资源管理: 如果代理对象涉及到资源的管理,如内存释放、文件关闭等,需要确保代理对象在不再使用时能够正确地进行资源清理,以避免资源泄漏。
  5. 并发安全: 如果多个线程同时访问代理对象,需要考虑并发安全性。适当的同步机制可能需要用于保护代理对象的状态。
  6. 生命周期管理: 代理对象的生命周期需要得到管理,包括创建、销毁和内存管理。确保代理对象在不再需要时能够正确地释放资源。
  7. 应用场景: 代理模式并不适用于所有情况。在一些简单的场景中,直接使用真实对象可能更简单和直观。只有在需要控制访问、添加额外功能、延迟加载等情况下,才考虑使用代理模式。
  8. 不应过度使用: 代理模式是为了控制访问,而不是为了简单地添加功能。过度使用代理模式可能会引入不必要的复杂性,降低代码的可读性和维护性。

总之,代理模式在合适的场景下可以提供许多好处,但也需要权衡好处和代理所引入的复杂性、性能和维护成本。在使用代理模式时,需根据具体情况谨慎决策,并确保代理对象能够正确地管理资源和状态。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/950017.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DSP_TMS320F28377D_算法加速方法2_添加浮点运算快速补充库rts2800_fpu32_fast_supplement.lib

继上一篇博客DSP_TMS320F28377D_算法加速方法1_拷贝程序到RAM运行_江湖上都叫我秋博的博客-CSDN博客之后&#xff0c;本文讲第二种DSP算法加速的方法&#xff0c;该方法的加速效果很明显&#xff0c;但是加速范围仅限于32位浮点数下面这几种函数: 1 工程师的关注点 下面稍微解…

CentOS8安装mysql8.0.24

一、下载mysql安装包并解压 执行以下命令&#xff1a; # 创建mysql安装目录 mkdir /usr/local/mysql # 进入mysql安装目录 cd /usr/local/mysql/ # 下载mysql-8.0.24 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.24-linux-glibc2.12-x86_64.tar.xz # 解压…

防静电出入门禁管理系统的功能和特点

防静电出入门禁管理系统是一种应用于电子设备生产、仓储物流等领域的门禁系统&#xff0c;旨在防止静电对于设备和产品的损害和干扰。该系统主要包括以下几个方面的功能和特点&#xff1a; 1. 门禁控制功能&#xff1a;通过在入口设置读卡器或生物识别设备&#xff08;如指纹、…

Java处理 CDT时区转换CST时区

例如&#xff1a;夏令营时间&#xff08;“Sat Aug 01 00:00:00 CDT 1987”&#xff09; //TODO CDT时区转换CST时区Date date new Date(value);TimeZone cdtTZ TimeZone.getTimeZone("America/Chicago");TimeZone cstTZ TimeZone.getTimeZone("America/Mexi…

SQL server数据库-定制查询-指定查询列/行、结果排序和Like模糊查询

本篇讲述进阶查询方法&#xff0c;如有语句不明确&#xff0c;可跳转本文专栏学习基础语法 1、指定列查询 特点 只会显示你输入的列的数据&#xff0c;会根据你输入的顺序进行显示&#xff0c;可以自定义查询显示时的列名 &#xff08;1&#xff09;只会显示你输入的列的数…

解析msvcp100.dll丢失的原因及修复方法,教你快速解决的方案

msvcp100.dll文件的丢失&#xff0c;其实也是属于dll丢失的其中一种&#xff0c;因为它是dll文件&#xff0c;大家记住&#xff0c;只要是后缀是dll的文件那么它就是dll文件&#xff0c;只要丢失了dll文件&#xff0c;那么其解决的方法都是大同小异的&#xff0c;唯一不同的是&…

分布式集群——jdk配置与zookeeper环境搭建

系列文章目录 分布式集群——jdk配置与zookeeper环境搭建 分布式集群——搭建Hadoop环境以及相关的Hadoop介绍 文章目录 系列文章目录 前言 一 zookeeper介绍与环境配置 1.1 zookeeper的学习 1.2 Zookeeper的主要功能 1.2.1 znode的节点类型 1.2.2 zookeeper的实现 …

【数据同步】如何快速同步第三方平台数据?

文章目录 前言1. 如何快速同步历史数据&#xff1f;2. 如何使用SFTP&#xff1f;2.1 账号权限控制2.2 统一数据格式2.3 使用job同步数据 3. 增量数据如何处理&#xff1f;4. 如何校验数据一致性&#xff1f; 前言 最近知识星球中有位小伙伴问了我一个问题&#xff1a;如何快速…

Navicat16连接Oracle报错:Oracle library is not loaded

1、有时候我们在用navicat的时候连接oracle的时候&#xff0c;它会提示我们Oracle library is not loaded&#xff0c;这时候我们要首先验证本机上是否已安装oracle的客户端&#xff0c;如果已安装客户段&#xff0c;navicat中的oci.dll选择我们安装的客户段的oci.dll文件 2、…

【C进阶】深度剖析数据在内存中的存储

目录 一、数据类型的介绍 1.类型的意义&#xff1a; 2.类型的基本分类 二、整形在内存中的存储 1.原码 反码 补码 2.大小端介绍 3.练习 三、浮点型在内存中的存储 1.一个例子 2.浮点数存储规则 一、数据类型的介绍 前面我们已经学习了基本的内置类型以及他们所占存储…

PyTorch 深度学习实践 第10讲刘二大人

总结&#xff1a; 1.输入通道个数 等于 卷积核通道个数 2.卷积核个数 等于 输出通道个数 1.单通道卷积 以单通道卷积为例&#xff0c;输入为&#xff08;1,5,5&#xff09;&#xff0c;分别表示1个通道&#xff0c;宽为5&#xff0c;高为5。假设卷积核大小为3x3&#xff0c…

直线模组选型的参考要素有哪些?

直线模组在自动化行业领域使用广泛&#xff0c;在不同设备运用直线模组&#xff0c;相对来说区别还是比较大的&#xff0c;而选择直线模组也是有很多要素决定的&#xff0c;因此懂得直线模组的选型也是至关重要的。 很多人都觉得选型是比较困难的&#xff0c;尤其是对于公司采购…

Ansible学习笔记10

1、在group1的被管理机里的mariadb里创建一个abc库&#xff1b; 1&#xff09; 然后我们到agent主机上进行检查&#xff1a; 可以看到数据库已经创建成功。 再看几个其他命令&#xff1a; #a组主机重启mysql&#xff0c;并设置开机自启 ansible a -m service -a "namemy…

Java中异或操作和OTP算法

最近在研究加密算法&#xff0c;发现异或操作在加密算法中用途特别广&#xff0c;也特别好用。下面以Java语言为例&#xff0c;简单记录一下异或操作&#xff0c;以及在算法中的使用&#xff0c;包括常用的OTP算法。 一&#xff0c;异或操作特征 1&#xff0c; 相同出0&#…

二分类问题使用rmse训练会是什么结果

通常情况下&#xff0c;使用均方根误差&#xff08;RMSE&#xff0c;Root Mean Square Error&#xff09;来训练二分类问题可能并不是最优选择&#xff0c;因为RMSE通常用于衡量连续值的预测误差&#xff0c;而不是分类问题。二分类问题更常用的衡量标准是交叉熵损失&#xff0…

行业追踪,2023-08-30

自动复盘 2023-08-30 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

java八股文面试[数据库]——MySql聚簇索引和非聚簇索引索引区别

聚集索引和非聚集索引 聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致。 1、聚集索引 聚集索引表记录的排列顺序和索引的排列顺序一致&#xff08;以InnoDB聚集索引的主键索引来说&#xff0c;叶子节点中存储的就是行数据&#xff0c;行数据在…

使用errors.Wrapf()代替log.Error()

介绍不同语言的错误处理机制: Error handling patterns[1] Musings about error handling mechanisms in programming languages[2] 项目中 main调func1&#xff0c;func1调取func2... 这样就会出现很多的 if err ! nil { log.Printf()} , 在Kibana上查看时会搜到多条日志, 需要…

解决iPad故障问题的三种重置方式:出厂恢复、软重置和强制重启

这篇文章解释了如何重新启动iPad,以及如果它没有响应,如何强制它重新启动。它还包括如何重置iPad的其他选项。 一、重启iPad的最简单方法(所有型号) 基本的重新启动是最容易做到的,也是遇到硬件问题时应该尝试的第一件事。该过程不会删除你的数据或设置。请执行以下步骤…