软件设计模式系列之十四——代理模式

news2024/12/23 5:22:18

1 模式的定义

代理模式是一种结构型设计模式,它允许一个对象(代理)充当另一个对象的接口,以控制对该对象的访问。代理模式通常用于控制对真实对象的访问,以实现一些额外的功能,例如延迟加载、权限控制、日志记录等。这种模式属于结构型设计模式,因为它关注对象之间的组合,以形成更大的结构。

代理模式有多种类型,包括静态代理和动态代理。静态代理在编译时创建代理对象,而动态代理在运行时创建代理对象。代理模式的核心思想是通过引入一个代理对象来控制对真实对象的访问,从而实现额外的功能,而不必修改真实对象的代码。

2 举例说明

为了更好地理解代理模式,让我们看几个日常生活中的简单示例。
一个最典型的例子就是狐假虎威,狐狸就做了老虎的代理。
在这里插入图片描述

银行代理。在银行业务中,某些操作需要前往银行分行才能完成,但人们不一定都会前往分行。因此,银行通常设立代理机构,例如ATM(自动取款机)和在线银行,允许客户在不必亲自前往分行的情况下进行银行业务。

网络代理。防火墙和代理服务器是网络中常见的代理示例。防火墙代理可以过滤和控制网络流量,而代理服务器可以缓存和优化网络请求,提高网络性能。
在这里插入图片描述

租房中介。在房地产市场中,房屋租赁中介机构充当租客和房东之间的代理。中介机构帮助租客找到合适的房源,同时为房东管理租赁过程,收取一定的服务费。

电影票代理。在线电影票代理网站允许观众在不必亲自前往电影院的情况下购买电影票。这些代理网站提供了方便的在线订票和座位选择功能。

社交媒体代理。在社交媒体上,一些名人或公众人物可能雇佣社交媒体代理来管理他们的社交媒体账户。这些代理负责发布内容、与粉丝互动,以代表名人或公众人物维护其在线存在。

这些示例都展示了代理模式的核心思想:允许一个对象(代理)充当另一个对象(真实对象)的接口,以控制对真实对象的访问,同时可以添加额外的功能或服务。这种模式在日常生活中有着广泛的应用,以提供更便利的服务和更好的控制。

3 结构

代理模式的结构包括以下几个关键部分:
在这里插入图片描述

Subject(主题):定义了真实对象和代理对象的共同接口,以确保代理对象可以替代真实对象。在示例中,ImageLoader 就是主题。

RealSubject(真实主题):代表真实对象,它是实际执行工作的类。在示例中,ImageLoader 是真实主题。

Proxy(代理):充当了真实主题的代理,实现了与真实主题相同的接口。它可以在执行任务前后添加额外的功能。在示例中,ImageLoaderProxy 是代理。

4 实现步骤

实现代理模式时,通常遵循以下步骤:

定义主题接口(Subject):这个接口应该包含真实主题和代理类都必须实现的方法。

创建真实主题类(RealSubject):这个类负责执行实际的工作,实现主题接口的方法。

创建代理类(Proxy):代理类实现了主题接口,并包含一个对真实主题对象的引用。它可以在调用真实主题的方法前后添加额外的逻辑。

在客户端代码中使用代理:客户端代码不直接与真实主题交互,而是通过代理对象来访问真实主题。

5 代码实现

假设我们有一个图像加载器类 ImageLoader,它负责从磁盘或网络加载图像并显示在界面上。现在,我们想要在加载图像之前检查用户的权限以确保他们有权查看该图像。

在这个示例中,我们可以创建一个代理类 ImageLoaderProxy,它充当了 ImageLoader 的接口。在代理类中,我们可以添加权限检查的逻辑,然后再调用真实的 ImageLoader 对象来加载图像。

// 1. 定义主题接口
interface ImageLoader {
    void displayImage();
}

// 2. 创建真实主题类
class RealImageLoader implements ImageLoader {
    private String image;

    public RealImageLoader(String image) {
        this.image = image;
    }

    @Override
    public void displayImage() {
        System.out.println("Displaying image: " + image);
    }
}

// 3. 创建代理类
class ImageLoaderProxy implements ImageLoader {
    private RealImageLoader realImageLoader;
    private String image;
    private String user;

    public ImageLoaderProxy(String image, String user) {
        this.image = image;
        this.user = user;
    }

    @Override
    public void displayImage() {
        // 在调用真实主题前检查用户权限
        if (user.equals("admin")) {
            realImageLoader = new RealImageLoader(image);
            realImageLoader.displayImage();
        } else {
            System.out.println("Access denied. You do not have permission to view this image.");
        }
    }
}

// 4. 在客户端代码中使用代理
public class Client {
    public static void main(String[] args) {
        ImageLoader imageLoader = new ImageLoaderProxy("image.jpg", "admin");
        imageLoader.displayImage();

        ImageLoader imageLoader2 = new ImageLoaderProxy("image.jpg", "user");
        imageLoader2.displayImage();
    }
}

6 典型应用场景

代理模式在软件开发中有许多典型的应用场景,包括但不限于:

虚拟代理(Virtual Proxy):延迟加载。用于延迟加载大型资源,例如图像或文件,以提高性能。虚拟代理只在需要时加载真实对象,而不是在初始化时加载。
在这里插入图片描述

远程代理(Remote Proxy):远程服务访问。用于通过网络访问远程对象,隐藏了底层的网络通信细节。客户端可以像调用本地对象一样访问远程对象。

保护代理(Protection Proxy):权限控制。用于控制对对象的访问,确保只有合适的用户或客户端可以访问真实对象。通常用于实现身份验证和授权。

缓存代理(Cache Proxy):缓存管理。用于在访问对象之前检查缓存,以提高性能。如果请求的数据已存在于缓存中,代理会返回缓存的数据而不是重新加载。

日志记录代理(Logging Proxy):用于在调用真实对象的方法前后添加日志记录,以监控和记录系统行为。

动态代理(Dynamic Proxy):运行时代理。用于在运行时创建代理对象,通常通过Java的反射机制实现。动态代理可以实现通用的代理逻辑,而不需要为每个接口或对象单独创建代理类。

这些应用场景和功能分类展示了代理模式的灵活性和多样性。根据具体的需求和情况,可以选择使用代理模式的不同变体来实现所需的功能,从而提高代码的可维护性和灵活性

7 优缺点

优点:
控制访问:代理模式允许你控制对真实对象的访问,可以添加额外的逻辑来满足特定需求,如权限控制、日志记录等。

提高性能:虚拟代理和缓存代理可以提高性能,延迟加载和缓存对象可以减少不必要的资源消耗。

松耦合:代理模式可以将客户端与真实对象解耦,客户端不需要直接访问真实对象,从而降低了耦合度。

安全性:代理模式可以用于实现安全性控制,确保只有符合条件的用户或客户端可以访问真实对象。
缺点:
复杂性增加:引入代理对象可能会增加代码复杂性,特别是在涉及多个代理层的情况下。

性能开销:在一些情况下,代理模式可能引入性能开销,特别是在创建代理对象的开销较大时。

8 类似模式

与代理模式类似的模式包括装饰器模式和适配器模式。这些模式与代理模式有一些相似之处,但它们各自有不同的目的和应用场景。

装饰器模式(Decorator Pattern)

装饰器模式的主要目的是动态地为对象添加额外的功能,而不改变其接口。它通过将对象包装在装饰器类中来实现这一点。代理模式和装饰器模式都允许你包装对象并添加额外的功能。它们都通过组合实现,都有一个共同的接口,但其关注点不同。代理模式关注于控制访问和添加额外逻辑,而装饰器模式关注于动态添加功能,但不改变接口。

适配器模式(Adapter Pattern)

适配器模式的主要目的是将一个接口转换为另一个接口,以便两个不兼容的接口可以协同工作。它通常涉及到两个已存在的接口之间的适配。代理模式和适配器模式都涉及到包装对象。然而,代理模式主要关注于控制对真实对象的访问,而适配器模式主要关注于接口的转换。

9 小结

代理模式是一种有用的设计模式,用于控制对真实对象的访问并添加额外的功能。它在许多应用场景中都有广泛的用途,包括权限控制、延迟加载、性能优化等。通过引入代理对象,可以实现松耦合的设计,使系统更加灵活和可维护。然而,代理模式也需要谨慎使用,因为不当使用可能会引入复杂性和性能开销。在实际开发中,要根据具体需求和场景来选择是否使用代理模式以及何种类型的代理模式。希望本文能够帮助你更好地理解代理模式的概念和应用。

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

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

相关文章

ORM模型与表的映射

ORM模型与表的映射 ORM模型 对象关系映射(ObjectRelationship:Mapping),简称 ORM,是一种可以用 Python 面向对象的方式来操作关系型数据库的技术,具有可以映射到数据库表能力的 Python 类我们称之为 ORM 模型。一个 ORM 模型与数据库中一个…

基于SpringBoot的的师生健康信息管理系统

目录 前言 一、技术栈 二、系统功能介绍 管理员功能模块 学生功能模块 教师功能模块 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着移动应用技术的发展,越来越多的用户借助于移动手机、电脑完成生活中的事务,许多的传统行业也…

华为NFC设置教程(门禁卡/公交卡/校园卡等)

今天把华为NFC设置教程分享给大家 出门带门禁卡、校园卡、银行卡、身份证……东西又多,携带又麻烦,还容易搞丢,有没有一种方法可以把它们都装下?有!只要一部手机,出门不带卡包,各种证件&#x…

SpringCloud Alibaba 入门到精通 - Sentinel

SpringCloud Alibaba 入门到精通 - Sentinel 一、基础结构搭建1.父工程创建2.子工程创建 二、Sentinel的整合SpringCloud1.微服务可能存在的问题2.SpringCloud集成Sentinel搭建Dashboard3 SpringCloud 整合Sentinel 三、服务降级1 服务降级-Sentinel2 Sentinel 整合 OpenFeign3…

算法之斐波那契数列

10.1 斐波那契数列 题目链接 牛客网 题目描述 求斐波那契数列的第 n 项&#xff0c;n < 39。 解题思路 如果使用递归求解&#xff0c;会重复计算一些子问题。例如&#xff0c;计算 f(4) 需要计算 f(3) 和 f(2)&#xff0c;计算 f(3) 需要计算 f(2) 和 f(1)&#xff0c;…

好物周刊#9:AI 学习必备资料

村雨遥的好物周刊&#xff0c;记录每周看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;每周五发布。 一、项目 1. PicX 一款基于 GitHub API 开发的图床工具&#xff0c;提供图片上传托管、生成图片链接和常用图片工具箱服务。只需要申请一个 Github Token&am…

[Python]Open CV 基础知识学习

Open CV 在图像处理与目标检测中应用比较广&#xff0c;因此来学习一下基础知识。 Open CV 的安装: 在anaconda search中找opencv&#xff0c; 然后anaconda会自动安装opencv和关联的库 Open CV 基本操作: 注意python 中导入opencv的包名是cv2 读取图片: imread有两个参数…

力扣 -- 215. 数组中的第K个最大元素

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int QuickSelectSort(vector<int>& nums,int begin,int end,int k){//随机选keyint keynums[beginrand()%(end-begin1)];//left在左端点前一个位置int leftbegin-1;//right在右端点后一个位置in…

LDA算法并提取这份数据集中各个文档的主题

任务描述&#xff1a;现有一份“网易新闻语料”数据集&#xff0c;请尝试用Python或Java实现LDA算法并提取这份数据集中各个文档的主题&#xff0c;并显示出来&#xff08;可参考下图的输出结果&#xff0c;可网上拷贝代码&#xff0c;但需对算法以及代码有一定的基本了解&…

《从零开始的Java世界》01基本程序设计

《从零开始的Java世界》系列主要讲解Javase部分&#xff0c;从最简单的程序设计到面向对象编程&#xff0c;再到异常处理、常用API的使用&#xff0c;最后到注解、反射&#xff0c;涵盖Java基础所需的所有知识点。学习者应该从学会如何使用&#xff0c;到知道其实现原理全方位式…

Python 逢七拍手小游戏1.0

"""逢七拍手游戏介绍&#xff1a;逢七拍手游戏的规则是&#xff1a;从1开始顺序数数&#xff0c;数到有7&#xff0c;或者是7的倍数时&#xff0c;就拍一手。例如&#xff1a;7、14、17......70......知识点&#xff1a;1、循环语句for2、嵌套条件语句if/elif/e…

【前段基础入门之】=>HTML结构进阶【列表;表格;表单】

前言 在上一章节中&#xff0c;我们学习了讲述了 html 中的一些常用排版标签&#xff0c;以及一些文本标签和超链接等相关知识。本章节将重点给大家带来 HTML 中【列表&#xff0c;表格&#xff0c;表单】的使用讲解。 目录 列表有序列表无序列表自定义列表 表格表格的基本结构…

在项目中使用Service Worker 与 PWA

小册 这是我整理的学习资料&#xff0c;非常系统和完善&#xff0c;欢迎一起学习 现代JavaScript高级小册 深入浅出Dart 现代TypeScript高级小册 linwu的算法笔记&#x1f4d2; 引言 最近next项目有使用pwa技术&#xff0c;使用起来也不复杂&#xff0c;目前浏览器的兼容…

【hadoop3.x】一 搭建集群调优

一、基础环境安装 https://blog.csdn.net/fen_dou_shao_nian/article/details/120945221 二、hadoop运行环境搭建 2.1 模板虚拟机环境准备 0&#xff09;安装模板虚拟机&#xff0c;IP 地址 192.168.10.100、主机名称 hadoop100、内存 4G、硬盘 50G 1&#xff09;hadoop100…

MongoDB基础详解

一、MongoDB概述 MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统&#xff0c;由 C 编写的。MongoDB 提供了 面向文档 的存储方式&#xff0c;操作起来比较简单和容易&#xff0c;支持“无模式”的数据建模&#xff0c;可以存储比较复杂的数据类型&#xff0c;是一…

MySQL的general日志

起因是一个客户的MySQL数据的data目录下会生成一个 名为ubuntu.log的日志且文件占用空间极大&#xff0c;平均每2周500G&#xff0c;所以才产生了处理该问题的想法。后来查询了相关资料其实就是一般日志开启了&#xff0c;但是又未指定其路径及名称所以就会一头雾水。 MySQL的g…

关于华为笔记本谷歌浏览器(chrome)默认启动页为360搜索的解决方法

一、简介 好久没打开谷歌浏览器&#xff0c;近期发现谷歌浏览器的启动是360搜素&#xff0c;现象比较常见&#xff0c;一开始以为是被各种病毒或插件拦截&#xff0c;经过很多尝试方法&#xff1a; 修改浏览器启动页设置【无效】修改快捷方式的“目标位置”属性【无效】修改&…

MySQL:码包安装mysql(5.6.51)

我们去下载mysql源码安装包和cmake包 安装mysql的时候需要使用到cmake&#xff0c;其次我们还要使用yum安装一些环境 yum -y install ncurses-devel gcc-c gcc openssl* perl* 下载mysql源码包 http://mirrors.sohu.com/mysql/MySQL-5.6/mysql-5.6.51.tar.gzhttp://mirrors.s…

WebRTC之丢包重传协议

丢包处理可以使用FEC前向纠错、NACK丢包重传。上一篇文章咱们介绍过前向纠错&#xff0c;现在来探讨丢包重传。首先是接收端发送基于RTCP反馈的请求&#xff0c;发送端收到请求后重传指定packet包。 1、重传包格式 重传包的格式由RTP头、OSN、原始payload数据组成。OSN表示原…

Prometheus+Grafana实现监控报警

文章目录 一、PrometheusGrafana实现监控报警1.1 各项服务端口1.2 说明 二、部署2.1 展示 一、PrometheusGrafana实现监控报警 Prerequired K8s集群 1.1 各项服务端口 Service版本DescriptionPortNode-exporter1.6.1采集机器的各项监控指标9100Pushgatewayv1.6.2可手动push…