设计模式结构型模式之代理模式

embedded/2024/9/20 1:27:17/ 标签: 设计模式, 代理模式

结构型模式之代理模式

  • 一、概念和使用场景
    • 1、概念
    • 2、核心思想
    • 3、java实现代理模式的方式
    • 4、使用场景
  • 二、示例讲解
    • 1. 静态代理
    • 2. 动态代理
  • 三、总结

一、概念和使用场景

1、概念

代理模式是一种结构型设计模式,它允许我们为其他对象提供一个代理或者占位符,以控制对该对象的访问。

2、核心思想

代理模式的核心思想是在访问一个对象时引入一个代理对象,通过代理对象来控制访问的权限和行为。代理对象和被代理对象具有相同的接口,这样客户端就可以通过代理对象来访问被代理对象。代理对象可以拦截对被代理对象的访问,并添加额外的逻辑,例如权限检查、缓存等。

3、java实现代理模式的方式

在Java中实现代理模式有两种方式:静态代理和动态代理

4、使用场景

Java代理模式的使用场景有以下几个:

  1. 远程代理:当对象存在不同地址空间时,可以使用远程代理来隐藏对象的具体实现细节,使得客户端可以像访问本地对象一样访问远程对象。远程代理主要用于网络通信中的远程方法调用。

  2. 虚拟代理:当创建一个对象需要很长时间时(例如加载大量数据或者进行复杂的计算),可以使用虚拟代理来延迟对象的创建。虚拟代理在真正需要使用对象时才会创建,可以节省系统资源。

  3. 安全代理:当需要控制对某个对象的访问权限时,可以使用安全代理来限制对对象的直接访问。安全代理可以在访问对象之前进行权限验证,确保只有具有相应权限的用户才能访问对象。

  4. 缓存代理:当需要缓存对象的结果时,可以使用缓存代理来提高系统的性能。缓存代理会在调用对象的方法之前检查缓存,如果缓存中已经存在相同的结果,则直接返回缓存中的结果,而不去真正执行方法。

  5. 日志记录代理:当需要记录对象的操作日志时,可以使用日志记录代理来实现。日志记录代理会在调用对象的方法之前进行日志记录,可以记录下对象的操作信息,方便后续的审计和分析。

总之,代理模式可以在不改变原有对象的情况下,通过引入代理对象来增加一些额外的功能,提供更好的控制和封装。

二、示例讲解

1. 静态代理

静态代理是在编译时就已经确定代理对象的类型,代理对象和被代理对象都需要实现同一个接口。代理对象在调用被代理对象的方法前后可以执行一些额外的逻辑。

下面是一个简单的静态代理的示例代码:
定义一个接口 SaleHouse

//待出售房产
public interface SaleHouse {//房产信息Object    houseInformation(String price);
}

被代理的角色(房子主人) HouseOwner

package org.storemanage.regestercenter.proxymode;/*** @CreateTime: 2024-08-30* @Description: 房屋主人* @Version: 1.0* @Author: hkf*/public class HouseOwner implements SaleHouse {private final String  name ="阳光别墅区";private final  String address ="四川省成都市武侯区双楠大道xxx小区123号";private String price;@Overridepublic Object houseInformation(String price) {String  houseInfo ="200 W";if (!price.isEmpty()) {houseInfo=  "房产名称:"+name+"\n 地址为:"+address+"\n房产价格为:"+price;}return houseInfo ;}public String getPrice() {return price;}public void setPrice(String price) {this.price = price;}@Overridepublic String toString() {return "HouseOwner{" +"name='" + name + '\'' +", address='" + address + '\'' +", price='" + price + '\'' +'}';}
}

代理角色 (房屋中介) HouseAgent

package org.storemanage.regestercenter.proxymode;/*** @CreateTime: 2024-08-30* @Description: 房屋中介* @Version: 1.0* @Author: hkf*/public class HouseAgent implements SaleHouse {private   String  price;public String getPrice() {return price;}public void setPrice(String price) {this.price = price;}HouseOwner  houseOwner;//中介为了赚佣金,提高了出售的价格@Overridepublic Object houseInformation(String price) {Object houseInfo ="";if (houseOwner == null) {houseOwner = new HouseOwner();houseInfo = houseOwner.houseInformation(price);}return houseInfo;}@Overridepublic String toString() {return "HouseAgent{" +"price='" + price + '\'' +", houseOwner=" + houseOwner +'}';}
}

客户端调用者 ClientHouseAgent

package org.storemanage.regestercenter.proxymode;/*** @CreateTime: 2024-08-30* @Description: 客户端代理实现* @Version: 1.0* @Author: hkf*/public class ClientHouseAgent {public static void main(String[] args) {HouseAgent houseAgent = new HouseAgent();//中介可以自定义价格,赚取佣金Object houseInfo = houseAgent.houseInformation("236 w");System.out.println(houseInfo);}}

结果如图
在这里插入图片描述

2. 动态代理

动态代理是在运行时通过反射机制动态生成代理对象,代理对象不需要实现接口,但需要指定一个接口或者父类来实现代理。

下面是一个简单的动态代理的示例代码:

定义接口 SaleHouse

package org.storemanage.regestercenter.proxymode;//待出售房产
public interface SaleHouse {//房产信息Object    houseInformation(String price);
}

定义被代理角色 HouseOwner

package org.storemanage.regestercenter.proxymode;/*** @CreateTime: 2024-08-30* @Description: 房屋主人* @Version: 1.0* @Author: hkf*/public class HouseOwner implements SaleHouse {private final String  name ="阳光别墅区";private final  String address ="四川省成都市武侯区双楠大道xxx小区123号";private String price;@Overridepublic Object houseInformation(String price) {String  houseInfo ="200 W";if (!price.isEmpty()) {houseInfo=  "房产名称:"+name+"\n 地址为:"+address+"\n房产价格为:"+price;}return houseInfo ;}public String getPrice() {return price;}public void setPrice(String price) {this.price = price;}@Overridepublic String toString() {return "HouseOwner{" +"name='" + name + '\'' +", address='" + address + '\'' +", price='" + price + '\'' +'}';}
}

创建代理角色 HouseAgentInvocationHandler

package org.storemanage.regestercenter.proxymode;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** @CreateTime: 2024-08-30* @Description: 中介动态代理* @Version: 1.0* @Author: hkf*/public class HouseAgentInvocationHandler implements InvocationHandler {private Object  target;public HouseAgentInvocationHandler(Object  target){this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method: " + method.getName());Object invoke = method.invoke(target, args);System.out.println(" After  method: " + method.getName());return invoke;}
}

客户端代码 ClientHouseDemo

package org.storemanage.regestercenter.proxymode;import java.lang.reflect.Proxy;/*** @CreateTime: 2024-08-30* @Description: 动态代理客户端代码* @Version: 1.0* @Author: hkf*/public class ClientHouseDemo {public static void main(String[] args) {HouseOwner houseOwner = new HouseOwner();HouseAgentInvocationHandler handler = new HouseAgentInvocationHandler(houseOwner);SaleHouse saleHouse=(SaleHouse)Proxy.newProxyInstance(houseOwner.getClass().getClassLoader(), houseOwner.getClass().getInterfaces(),handler);Object o1 = saleHouse.houseInformation("443 W");System.out.println(o1);}
}

结果如图
在这里插入图片描述
在上述代码中,我们首先定义了一个接口 SaleHouse ,然后实现了该接口的具体类 HouseOwner 。接着,定义了 HouseAgentInvocationHandler 类作为动态代理的 InvocationHandler ,在 invoke 方法中可以添加额外的逻辑。在客户端代码中,我们创建了 HouseOwner 对象和 HouseAgentInvocationHandler 对象,然后利用 Proxy 类的 newProxyInstance 方法生成代理对象,最后调用代理对象的 houseInformation 方法。

三、总结

1、使用规则

无论是静态代理还是动态代理,代理模式都可以在不改变被代理对象的情况下,对访问进行控制和添加额外的逻辑。代理模式可以提高代码的可维护性和可扩展性,但也会增加代码的复杂性和性能开销,因此在使用代理模式时需要根据具体的情况进行权衡。

2、代理模式的优点包括:

  1. 代理模式可以实现真实对象的延迟加载。当真实对象的创建和初始化过程比较耗时时,使用代理模式可以在需要的时候才创建真实对象,提高系统的性能和响应速度。

  2. 代理模式可以提供额外的安全性控制。通过代理对象来控制对真实对象的访问,可以在访问前后进行一些额外的安全性检查和操作,增加系统的安全性。

  3. 代理模式可以实现对真实对象的访问控制和管理。通过代理对象可以控制对真实对象的访问和调用,可以实现一些额外的管理功能,如权限控制、缓存管理等。

3、代理模式的缺点包括:

  1. 代理模式增加了系统的复杂度。引入代理对象会增加系统中的类和对象的数量,增加系统的复杂度和维护成本。

  2. 代理模式可能会引入性能问题。由于代理模式引入了额外的层次,可能会在一定程度上降低系统的性能,特别是在频繁访问真实对象的情况下。

  3. 代理模式的设计需要考虑到代理对象和真实对象之间的接口的一致性,使得系统的设计和实现更加复杂。

在这里插入图片描述


http://www.ppmy.cn/embedded/105177.html

相关文章

如果你还不能完全明白什么是冒烟测试和回归测试的本质,那你就白干了

前言 对于很多刚入行的测试人员来说,对于冒烟测试和回归测试可能还不是十分熟悉,博为峰就和大家分享一下什么是冒烟测试与回归测试?如何才能做好它们? 1.何为冒烟测试 冒烟测试是自由测试的一种。冒烟测试在测试中发现问题&…

猎板PCB正片与负片工艺:深入解析PCB制造中的光刻技术及其应用

猎板PCB是一家专注于高品质印刷电路板(PCB)制造的领先企业。我们致力于为客户提供从设计到生产的一站式服务,包括但不限于单层、双层、多层PCB板的制造,以及复杂的正负片叠加工艺。 正负片叠加工艺在PCB制造中并不常见,因为正片和负片在光刻…

HTTP、Session、Token及Cookie详解

HTTP(超文本传输协议) HTTP(Hypertext Transfer Protocol) 是用于在Web浏览器和Web服务器之间传输信息的协议。它是无状态的,这意味着每个请求都是独立的,服务器不会记住之前的请求状态。HTTP使用客户端-服…

Unity AudioSource.PlayClipAtPoint听不到声音的一种情况

AudioSource.PlayClipAtPoint是按距离来控制音量的,所以距离太远是听不到的。而这个距离是播放音乐自动生成的GameObject名称是One shot audio的位置(也就是输入的位置)到AudioListener的位置。 AudioListener的位置是由其挂在的GameObject …

C++类和对象2

一.类的默认成员函数 类的默认成员函数是用户自己没有显示写出,而编译器会自动生成的成员函数。当需要用到这些函数时,编译器就会自动生成并调用。但是当用户显示写出时,以后再调用就会调用用户写的,编译器不再自动生成。下面就是…

深度解析C++中函数重载与引用

🌈个人主页:Yui_ 🌈Linux专栏:Linux 🌈C语言笔记专栏:C语言笔记 🌈数据结构专栏:数据结构 🌈C专栏:C 文章目录 1. 函数重载1.1 函数重载概念1.2 C支持函数重载…

数据库之心:MySQL 探索(一)mysql的安装和基本介绍

欢迎来到我们的MySQL博客!在这里,我们将深入探讨MySQL数据库系统的各个方面,包括基础知识、优化技巧、实践案例以及最新的行业趋势。 目录 前言 什么是数据库? 数据库产品 MySQL安装 解压 配置 添加环境变量 初始化MySQL …

css基础学习总结(一)

文章目录 一. 选择器1. 标签选择器2. 类选择器3. ID选择器4. 分组选择器5. 派生与子元素选择器6. 属性选择器7. 伪类选择器8. 伪对象选择器9. 选择器的优先级别css优先级 的 6大分类 一. 选择器 1. 标签选择器 选择器例子描述elementp/div/span选择所有含有指定标签的元素 &…

每周12600元奖金池,邀你与昇腾算力共舞,openMind开发者盛宴启幕!

小伙伴们,是否瞬间被这个标题唤醒了在OpenI启智社区“我为开源打榜狂”黄金时代的温馨记忆?打榜活动虽已谢幕,但大家相伴度过12期的那份激情与创新的共鸣,促使OpenI启智社区在国产算力崛起的浪潮中勇立潮头,推出了“芯…

集成电路学习:什么是ARM先进精简指令集计算机

ARM:先进精简指令集计算机 ARM先进精简指令集计算机(Advanced RISC Machine,简称ARM)是一种基于精简指令集计算机(RISC)原则的计算机处理器架构,由英国的ARM公司开发。这种架构以其低功耗和高性…

【GPT】Coze使用开放平台接口-【6】Dify 也来一遍

前面讲了 coze 的相关用法,这边想着用 Dify 也来一遍,刚开始的时候接触的是 Dify,后面才是 coze。Dify 和 coze 的侧重点不同,我个人是更倾向用 Dify 构建工作流就可以了,coze 还是相对全能。 本节用 Dify 也会创建插…

代码随想录 刷题记录-24 图论 (1)理论基础 、深搜与广搜

一、理论基础 参考: 图论理论基础 深度优先搜索理论基础 广度优先搜索理论基础 dfs dfs搜索可一个方向,并需要回溯,所以用递归的方式来实现是最方便的。 有递归的地方就有回溯,例如如下代码: void dfs(参数) {…

MySQL-CGI-响应报文

账号密码涉及到: 与数据库已记录下来的进行校验。 如果也是来一个新建一个连接,必然效率低。 可以做一个数据库连接池,预生成数据库连接。 如何生成数据库连接?下面的流程做很多次。 然后放在链表中,(池&am…

macos MacPort 包管理工具安装和使用

在macos v10.15版本中, xz, python等软件无法使用brew安装, 原因是brew对于旧版本的macos不再支持, 但是我们可以使用另外一个macos下的包管理工具来安装brew无法安装的软件, macport 是一个和brew类似的macos下的一个非常优秀的软件包安装管理工具. MacPort安装前提条件 安…

科研绘图系列:R语言基因PPI互作网络图(PPI network plot )

介绍 基因的PPT互作网络图。 加载R包 导入所需要的R包,在导入前需要用户自己安装。 library("tidyverse") library("magrittr") library("here") library("janitor") library("ggpubr") library("ComplexHeatmap&…

【STM32】位带操作

一、位带操作 1.意义 回想以前写51代码 ​ P0 0x10; //将P0端口设置为0x10 P1_01; //将P1端口0号引脚设置为高电平 a P2_2; //获取P2端口2号引脚的电平 根据上述的方法,我们可以发现快速定位修改某个引脚的电平还有获取引脚的状态 2.原因 GPIO_SetBits、GPI…

Ubuntu 22.04 镜像自定义制作

Centos封装镜像> Linux Centos ISO镜像自定义制作 Ubuntu20.04封装镜像> Ubuntu 20.04 镜像自定义制作 1、下载镜像 系统环境:ubuntu 22.04 镜像地址:https://mirrors.aliyun.com/ubuntu-releases rootubuntu:~# apt install -y p7zip xorriso ro…

Python进阶08-爬虫

零、文章目录 Python进阶08-爬虫 1、爬虫介绍 (1)爬虫是什么 **网络爬虫:**又被称为网页蜘蛛,网络机器人,是一种按照一定的规则,自动地抓取网络信息的程序或者脚本,另外一些不常使用的名字还有蚂蚁、自…

应用层(Web与HTTP)

目录 常见术语 1.HTTP概况 2.HTTP连接 非持久HTTP流程 响应时间模型 持久HTTP 3.HTTP报文 3.1HTTP请求报文 3.2HTTP响应报文 HTTP响应状态码 4.Cookies(用户-服务器状态) cookies:维护状态 Cookies的作用 5.Web缓冲(…

视频智能分析打手机检测算法安防监控打手机检测算法应用场景、算法源码、算法模型介绍

随着智能手机的普及,手机已成为人们生活中不可或缺的一部分。然而,在某些场合,如驾驶、会议、学校课堂等,不当使用手机可能会导致安全隐患或干扰他人。因此,开发出一种能够准确识别并阻止不当使用手机的行为检测算法显…