二十三种设计模式-代理模式

一、定义与核心思想

代理模式是一种结构型设计模式,其核心思想是提供一个代理对象,用以控制对实际对象的访问。通过代理对象,可以在不改变实际对象的情况下,添加各种功能,如权限控制、懒加载、缓存、远程调用等。

二、组成要素

代理模式主要由以下几个要素组成:

  1. 抽象主题(Subject)

    • 这是一个接口或抽象类,定义了代理对象和实际对象共同的接口,使得代理对象可以在客户端中替代实际对象使用。

    • 例如,定义一个Subject接口,其中声明了request()方法。

  2. 实际主题(RealSubject)

    • 实现抽象主题接口的具体类,定义了代理所代表的真实对象。实际主题对象实现了业务逻辑,是客户端最终需要调用的对象。

    • 例如,RealSubject类实现了Subject接口,在request()方法中实现了具体的业务逻辑。

  3. 代理(Proxy)

    • 也实现了抽象主题接口,内部包含一个对实际主题对象的引用。代理对象在调用实际主题对象的方法前后可以添加额外的逻辑,从而控制对实际主题对象的访问。

    • 例如,Proxy类实现了Subject接口,并且有一个RealSubject类型的成员变量。在request()方法中,代理对象可以进行权限检查、日志记录等操作,然后调用实际主题对象的request()方法。

三、实现示例

以下是使用Java语言实现代理模式的一个简单示例:

// 抽象主题接口
interface Subject {void request();
}// 实际主题类
class RealSubject implements Subject {@Overridepublic void request() {System.out.println("实际对象的请求");}
}// 代理类
class Proxy implements Subject {private RealSubject realSubject;@Overridepublic void request() {preRequest();if (realSubject == null) {realSubject = new RealSubject();}realSubject.request();postRequest();}private void preRequest() {System.out.println("代理对象的预处理操作,如权限检查");}private void postRequest() {System.out.println("代理对象的后处理操作,如日志记录");}
}// 客户端代码
public class Client {public static void main(String[] args) {Subject proxy = new Proxy(); // 直接创建代理对象proxy.request(); // 通过代理对象调用方法}
}

在这个示例中,客户端通过代理对象proxy调用request()方法。代理对象在调用实际主题对象RealSubjectrequest()方法前后,分别进行了预处理和后处理操作,如权限检查和日志记录。

四、优点

  1. 职责分离

    • 代理对象可以将客户端与实际主题对象解耦,使得客户端不需要直接与实际主题对象交互,从而降低了系统的耦合度。

  2. 功能扩展

    • 代理对象可以在不修改实际主题对象的情况下,添加各种功能,如权限控制、缓存、懒加载等,符合开闭原则。

  3. 控制访问

    • 代理对象可以控制对实际主题对象的访问,例如,根据用户的权限决定是否允许调用实际主题对象的方法。

  4. 远程调用

    • 代理对象可以处理远程方法调用的细节,如网络通信、序列化/反序列化等,使得客户端可以透明地调用远程对象的方法。

  5. 延迟加载

    • 代理对象可以实现懒加载,只有在第一次调用方法时才创建实际主题对象,从而提高系统的性能。

五、缺点

  1. 增加复杂性

    • 代理模式会增加系统的复杂性,因为需要创建额外的代理类和管理代理对象与实际对象之间的关系。

  2. 性能开销

    • 代理对象的调用会增加额外的性能开销,特别是当代理对象的逻辑比较复杂时,可能会对系统的性能产生一定的影响。

六、应用场景

  1. 权限控制

    • 通过代理对象可以控制对实际对象的访问权限,例如,根据用户的权限决定是否允许调用某个方法或访问某个资源。

    • 例如,实现一个权限控制代理,只有具备相应权限的用户才能通过代理对象调用实际对象的方法。

  2. 远程调用

    • 代理对象可以处理远程方法调用的细节,使得客户端可以透明地调用远程服务器上的方法。

    • 例如,使用RMI(Remote Method Invocation)技术实现远程对象调用,客户端通过代理对象调用远程服务器上的方法。

  3. 懒加载

    • 代理对象可以实现懒加载,只有在第一次调用方法时才创建实际对象,从而提高系统的性能。

    • 例如,加载一个大型的数据库连接对象时,可以使用懒加载代理来延迟创建连接对象,直到真正需要使用时才创建。

  4. 缓存

    • 代理对象可以缓存方法的调用结果,当再次调用相同的方法时,直接返回缓存的结果,从而提高系统的性能。

    • 例如,缓存网页的静态内容,当用户再次请求相同的内容时,直接从缓存中获取,而不需要重新生成。

  5. 日志记录

    • 代理对象可以在调用实际对象的方法前后记录日志,用于监控和调试。

    • 例如,记录方法的调用时间、参数、返回值等信息,帮助开发者进行问题定位和性能优化。

七、动态代理

除了静态代理,Java还支持动态代理。动态代理可以在运行时动态创建代理对象,而不需要在编译时定义代理类。动态代理主要使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现。

动态代理示例
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 抽象主题接口
interface Subject {void request();
}// 实际主题类
class RealSubject implements Subject {@Overridepublic void request() {System.out.println("实际对象的请求");}
}// 调用处理器
class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {preRequest();Object result = method.invoke(target, args);postRequest();return result;}private void preRequest() {System.out.println("代理对象的预处理操作,如权限检查");}private void postRequest() {System.out.println("代理对象的后处理操作,如日志记录");}
}// 客户端代码
public class Client {public static void main(String[] args) {Subject realSubject = new RealSubject(); // 创建实际主题对象MyInvocationHandler handler = new MyInvocationHandler(realSubject); // 创建调用处理器并传入实际主题对象Subject proxy = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), // 目标类加载器new Class<?>[]{Subject.class}, // 目标类实现的接口handler // 调用处理器);proxy.request(); // 通过代理对象调用方法}
}

在这个示例中,客户端通过Proxy.newProxyInstance方法动态创建了一个代理对象proxy。代理对象的调用处理器MyInvocationHandler在调用实际主题对象RealSubject的方法前后,分别进行了预处理和后处理操作。

总结

代理模式通过代理对象控制对实际对象的访问,可以在不修改实际对象的情况下,添加各种功能,如权限控制、懒加载、缓存、远程调用等。代理模式在实际开发中非常有用,选择静态代理还是动态代理取决于具体的需求和场景。

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

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

相关文章

SQL刷题快速入门(三)

其他章节&#xff1a; SQL刷题快速入门&#xff08;一&#xff09; SQL刷题快速入门&#xff08;二&#xff09; 承接前两个章节&#xff0c;本系列第三章节主要讲SQL中where和having的作用和区别、 GROUP BY和ORDER BY作用和区别、表与表之间的连接操作&#xff08;重点&…

ComfyUI 矩阵测试指南:用三种方法,速优项目效果

在ComfyUI中&#xff0c;矩阵测试也叫xyz图表测试&#xff0c;作用是通过控制变量的方式来对Lora模型以及各种参数开展测试&#xff0c;并进行有效区分。其中测试方法有很多种&#xff0c;可以通过借助插件也可以自行搭建工作流实现&#xff0c;下面介绍3种方式&#xff1a; 1…

在stm32中C语言编写的程序中,一个整形数据是怎么存储的,高位在前还是低位在前

目录 举个例子 如何验证 小结 在 STM32&#xff08;基于 ARM Cortex-M 架构&#xff09;的系统中&#xff0c;默认是小端&#xff08;Little Endian&#xff09; 存储方式。也就是说&#xff0c;对于一个整型&#xff08;例如 32 位 int&#xff09;&#xff0c;它的最低有效…

图数据库 | 19、高可用分布式设计(下)

相信大家对分布式系统设计与实现的复杂性已经有了一定的了解&#xff0c;本篇文章对分布式图数据库系统中最复杂的一类系统架构设计进行探索&#xff0c;即水平分布式图数据库系统&#xff08;这个挑战也可以泛化为水平分布式图数据仓库、图湖泊、图中台或任何其他依赖图存储、…

基于Python的多元医疗知识图谱构建与应用研究(上)

一、引言 1.1 研究背景与意义 在当今数智化时代,医疗数据呈爆发式增长,如何高效管理和利用这些数据,成为提升医疗服务质量的关键。传统医疗数据管理方式存在数据孤岛、信息整合困难等问题,难以满足现代医疗对精准诊断和个性化治疗的需求。知识图谱作为一种知识表示和管理…

Visual Studio Code + Stm32 (IAR)

记录一下&#xff0c; 以前看别人在 vsc 下配置 stm32 工程非常麻烦。 最近&#xff0c;突然发现&#xff0c; iar 官方出了两个插件&#xff0c; iar build 、 iar C-Spy 安装之后&#xff0c;配置一下 iar 软件路径。 然后&#xff0c;直接打开工程目录&#xff0c;编译…

oracle之行转列

对于Oracle的行转列功能一直云里雾里&#xff0c;马马虎虎&#xff0c;对行转列的使用场景和使用方法都不够深刻&#xff0c;最近有空理解一下。 Oracle 11g后有专门的函数pivot&#xff0c;对于特定的场景可以直接套用。 需求&#xff1a;求各份job不同员工工资是多少&#xf…

【Linux】Linux入门(4)其他常用指令

目录 软件安装yum命令 systemctl命令软链接IP地址和主机名特殊IP地址主机名域名解析 网络请求和下载ping命令wget命令curl命令 端口nmap指令 进程管理ps命令 查看进程kill 关闭进程 主机状态top命令 查看系统资源占用 软件安装 操作系统安装软件有许多种方式&#xff0c;一般分…

B站评论系统的多级存储架构

以下文章来源于哔哩哔哩技术 &#xff0c;作者业务 哔哩哔哩技术. 提供B站相关技术的介绍和讲解 1. 背景 评论是 B站生态的重要组成部分&#xff0c;涵盖了 UP 主与用户的互动、平台内容的推荐与优化、社区文化建设以及用户情感满足。B站的评论区不仅是用户互动的核心场所&…

蓝桥杯 阶乘的和(C++完整代码+详细分析)

题目描述 原题链接 阶乘的和 问题描述 给定 n 个数 Ai​&#xff0c;问能满足 m! 为 ∑(Ai!) 的因数的最大的 m 是多少。其中 m! 表示 m 的阶乘&#xff0c;即 123⋯m。 输入格式 输入的第一行包含一个整数 n。 第二行包含 n 个整数&#xff0c;分别表示 Ai​&#xff0c;相…

2024:成长、创作与平衡的年度全景回顾

文章目录 1.前言2.突破自我&#xff1a;2024年个人成长与关键突破3.创作历程&#xff1a;从构想到落笔&#xff0c;2024年的文字旅程4.生活与学业的双重奏&#xff1a;如何平衡博客事业与个人生活5.每一步都是前行&#xff1a;2024年度的挑战与收获6.总结 1.前言 回首2024年&a…

统信V20 1070e X86系统编译安装mysql-5.7.44版本以及主从构建

设备信息 操作系统版本架构CPU内存备注统信UOS V20 1070eX864C8G此配置仅做编译安装验证&#xff0c;持续运行或数据量增长大请自行评估资源配置。统信UOS V20 1070eX864C8G 资源包 该包包含mysql-5.7.44源码包、boost资源包、统信编译mysql-5.7.44安装包 通过网盘分享的文件…

4 AXI USER IP

前言 使用AXI Interface封装IP&#xff0c;并使用AXI Interface实现对IP内部寄存器进行读写实现控制LED的demo&#xff0c;这个demo是非常必要的&#xff0c;因为在前面的笔记中基本都需哟PS端与PL端就行通信互相交互&#xff0c;在PL端可以通过中断的形式来告知PS端一些事情&…

RoCE网络及其协议栈详解(没有中间商赚差价的网络)

引言 随着数据中心对高性能、低延迟通信需求的不断增长&#xff0c;传统的TCP/IP以太网连接已经难以满足现代应用的要求。为了解决这些问题&#xff0c;RDMA&#xff08;Remote Direct Memory Access&#xff09;技术应运而生。RDMA是一种允许网络中的不同计算机直接访问对方内…

回归预测 | MATLAB基于TCN-BiGRU时间卷积神经网络结合双向门控循环单元多输入单输出回归预测

效果一览 基本介绍 回归预测 | MATLAB基于TCN-BiGRU时间卷积神经网络结合双向门控循环单元多输入单输出回归预测 一、引言 1.1、研究背景及意义 在当今数据驱动的时代&#xff0c;时间序列预测已成为金融、气象、工业控制等多个领域的关键技术。随着人工智能和机器学习技术的…

HTML<img>标签

例子 如何插入图片&#xff1a; <img src"img_girl.jpg" alt"Girl in a jacket" width"500" height"600"> 下面有更多“自己尝试”的示例。 定义和用法 该<img>标签用于在 HTML 页面中嵌入图像。 从技术上讲&#x…

Linux--运维

Mysql主从同步 通过将MySQL的某一台主机&#xff08;master&#xff09;的数据复制到其他主机&#xff08;slaves&#xff09;上&#xff0c;并重新执行一遍来执行 复制过程中一台服务器充当主服务器&#xff0c;而其他一个或多个其他服务器充当从服务器 为什么要做主从复制 …

浅谈计算机网络03 | 现代网络组成

现代网络组成 一 、网络生态体系1.1网络生态系统的多元主体1.2 网络接入设施的多样类型 二、现代网络的典型体系结构解析三、高速网络技术3.1 以太网技术3.2 Wi-Fi技术的深度剖析3.2.1 应用场景的多元覆盖3.2.2 标准升级与性能提升 3.3 4G/5G蜂窝网的技术演进3.3.1 蜂窝技术的代…

[gpu驱动] H200 nvidia-fabricmanager-550升级到nvidia-fabricmanager-565报错,升级步骤

报错日志: root@h1-12-gpu:/home/canopy# apt install nvidia-fabricmanager-565 Reading package lists... Done Building dependency tree... Done Reading state information... Done Some packages could not be installed. This may mean that you have requested an imp…

LeetCode 110.平衡二叉树

题目描述 给定一个二叉树&#xff0c;判断它是否是平衡二叉树。 示例 1&#xff1a; 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,3,3,null,null,4,4] 输出&#xff1a;false 示例 3&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;true 提示&#xff1a; …