设计模式篇---代理模式

文章目录

    • 概念
    • 结构
    • 实例
      • 静态代理
      • 动态代理
    • 总结

概念

代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。
比如我们想从其他国家买东西,但我们无法直接联系外国的商家,可以找代理商,让他们帮我们处理,我们是客户端,只需要面向代理商即可,只需要把钱交给代理商,剩下的那些操作,比如联系商家、和商家签订协议等我们都不需要关心。

结构

在这里插入图片描述
Subject(抽象主题):它是代理类和真实类的共同接口,这样一来在任何使用真实对象的地方都可以使用代理对象,客户端通常需要针对抽象主题角色进行编程。
Proxy(代理类) :它包含了真实对象的引用,所以可以在任何时候操作真实对象。一般在调用真实对象前后还需要执行其他操作。
RealSubject(真实类–被代理类):真实类中实现了主要的业务操作。客户端可以调用代理类,来间接的调用真实类。

实例

静态代理

我们想从海外买台电脑,用代理模式实现这个流程。
在这里插入图片描述

购买东西的接口

public interface IBuySomething {void pay();
}

真实类,也就是被代理类

public class Person implements IBuySomething{@Overridepublic void pay() {System.out.println("付款");}
}

代理商,也就是代理类,他来帮我们联系商家

public class Agent implements IBuySomething {private IBuySomething person;public Agent(IBuySomething person) {this.person = person;}@Overridepublic void pay() {findBusiness();person.pay();}private void findBusiness() {System.out.println("我是代理商,付款之前先找到商家");}
}

客户端

public class Client {public static void main(String[] args) {IBuySomething person;person = new Agent(new Person());person.pay();}
}

打印结果:
在这里插入图片描述
也可以让代理商来替我们的朋友来买东西,只需要再声明一个朋友类,让代理商来代理即可。

朋友类

public class Friend implements IBuySomething{@Overridepublic void pay() {System.out.println("我是朋友,我付款");}
}

客户端

public class Client {public static void main(String[] args) {IBuySomething person;person = new Agent(new Friend());person.pay();}
}

打印结果
在这里插入图片描述
反过来,如果想换一家代理商,那就再创建一个新的代理商类即可。

public class Agent2 implements IBuySomething{private IBuySomething person;public Agent2(IBuySomething person) {this.person = person;}@Overridepublic void pay() {findBusiness();person.pay();}private void findBusiness() {System.out.println("我是另外一个代理商,付款之前先找到商家");}
}

动态代理

以上的这种代理方式叫做静态代理。
静态代理的特点是,一个代理类只能代理一个真实类,或者只能代理一个方法。因为它在执行前就编译成了class文件,不会进行改变了,所以被称为静态代理。
但如果我们想动态的代理不同的真实类,或者代理不同的方法,可以使用动态代理来实现。动态代理可以让系统在运行时根据实际需求来动态的创建代理类。
有关动态代理,有两个重要的类。
Proxy类
Proxy类提供了用于创建动态代理对象的方法。它的主要方法newProxyInstance

    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

该方法即用来创建一个动态代理对象;第一个参数是代理类的类加载器(作用是将.class文件加载到jvm中,进而生成一个对象实例);第二个参数是真实类实现的接口列表;第三个是执行代理方法的具体程序—InvocationHandler。
简单总结下,要想生成一个代理对象,首先得创建class对象(第一个参数的作用),其次得知道代理谁(第二个参数的作用),最后代理的方法是什么(第三个参数)。这样看来,第二个和第三个参数都是动态的,可变的,这也就是代理模式的灵活性。

InvocationHandler
上面的第三个参数InvocationHandler 是一个接口,它只有一个invoke方法

public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;

该方法用来处理代理类实例的代理方法,并返回相应的结果。即我们代理的方法写在这个方法里。
第一个参数是代理对象;第二个参数是需要代理的方法;第三个参数是需要执行代理方法的参数。

还是拿买东西的例子来说,我们如果买完东西后,发现不合适,需要退款,这时候我们面向的还是代理商,但如果用静态代理的话,那还是需要再写一个代理退款的类,如果业务方法更多的话,那我们需要创建更多的静态代理类,这样处理起来很麻烦。如果用动态代理的话,就没有这么冗余。我们首先实现一个InvocationHandler,它的invoke方法是用来实现代理对象的方法。

public class AgentHandler implements java.lang.reflect.InvocationHandler {private Object object;public AgentHandler(Object object) {this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {findBusiness();Object result = method.invoke(object, args);return result;}private void findBusiness() {System.out.println("我是代理商,我要先找到商家");}
}

我们也增加一个退款的方法

public interface IBuySomething {void pay();void refund();
}

客户端调用

public class Client {public static void main(String[] args) {IBuySomething person = new Person();InvocationHandler handler = new AgentHandler(person);Object o = Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), handler);IBuySomething proxy = (IBuySomething) o;proxy.refund();}
}

打印结果:
在这里插入图片描述

总结

静态代理比较好理解,代理类里面实现了代理的方法。
而动态代理的代理对象是通过Proxy创建的,代理的方法是在InvocationHandler里的invoke方法里,和静态代理对比的话,代理类和代理方法是分离开的。

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

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

相关文章

dell r720远程网络安装ubuntu20.04(无U盘)

登陆后界面&#xff0c;在主界面上&#xff0c;我们就可以看到各个硬件组件的状态。在快速启动任务栏中&#xff0c;可以对系统电源进行操作&#xff0c;如开机、关机等。安装操作系统&#xff0c;在虚拟控制台预览处点击>启动 按照浏览器出现的提示确定安装控件等&#x…

NSSCTF web刷题记录7

文章目录 [SDCTF 2022]CURL Up and Read [SDCTF 2022]CURL Up and Read 考点&#xff1a;SSRF 打开题目发现是curl命令&#xff0c;提示填入url 尝试http://www.baidu.com&#xff0c;成功跳转 将url的字符串拿去解码&#xff0c;得到json格式数据 读取下环境变量&#xff0c…

基础宠物商店管理系统(Java)大一程序设计

一.开发环境 Windows 11 -- JDK 21 -- IDEA 2021.3.3 二.需求 三.代码部分 //创建一个宠物类&#xff0c;被另外两类继承public class Pet {private String name;private int age;private String gender;private double cost0;//买进价格private double sellprice0;//卖出价…

【Spring】Spring统一功能处理

Spring统一功能处理 拦截器拦截器什么是拦截器拦截器的基本使用定义拦截器注册配置拦截器 拦截器详解拦截器的拦截路径配置拦截器实现原理初始化处理请求 适配器模式 统一数据返回格式统一数据返回格式快速入门 统一异常处理 拦截器 场景: 我们要对一个网站实现强制登陆的功能…

ChibiOS简介2/5

ChibiOS简介2/5 1. 源由2. ChibiOS基础知识2/52.4 Chapter 4 - ChibiOS General Architecture2.4.1 The Big Picture&#xff08;总体框图&#xff09;2.4.2 Embedded Components&#xff08;嵌入式组件&#xff09;2.4.3 Application Model&#xff08;应用模型&#xff09;2.…

爬虫解析——Xpath的安装及使用(五)

目录 一、Xpath插件的安装 二、安装 lxml 三、Xpath解析文件 1.解析本地文件 &#xff08;1&#xff09;导入本地文件 &#xff08;2&#xff09;解析本地文件 2.服务器文件解析 &#xff08;1&#xff09;获取网页源码 &#xff08;2&#xff09;解析服务器响应文件 …

TailwindCSS 如何处理RTL布局模式

背景 TikTok作为目前全世界最受欢迎的APP&#xff0c;需要考虑兼容全世界各个地区的本地化语言和阅读习惯。其中对于阿拉伯语、波斯语等语言的阅读书写习惯是从右向左的&#xff0c;在前端有一个专有名字RTL模式&#xff0c;即Right-to-Left。 其中以阿拉伯语作为第一语言的人…

建立个人学习观|地铁上的自习室

作者&#xff1a;向知 如果大家有机会来北京&#xff0c;可以来看看工作日早上八九点钟&#xff0c;15 号线从那座叫“顺义”的城市通向“望京”的地铁&#xff0c;你在那上面&#xff0c;能看到明明白白的&#xff0c;人们奔向梦想的模样。 一、地铁上的自习室 我在来北京之前…

【算法集训】基础数据结构:三、链表

链表就是将所有数据都用一个链子串起来&#xff0c;其中链表也有多种形式&#xff0c;包含单向链表、双向链表等&#xff1b; 现在毕竟还是基础阶段&#xff0c;就先学习单链表吧&#xff1b; 链表用头结点head表示一整个链表&#xff0c;每个链表的节点包含当前节点的值val和下…

2024 年顶级的 Android 系统修复软件与方法

您是否正在寻找可以修复 PC 上 Android 操作系统的工具&#xff1f;这是我们精选的最好的 Android 系统修复软件&#xff01; Android 是世界著名的智能手机操作系统。全世界有数百万人使用这个操作系统&#xff0c;这使得它安全可靠。然而&#xff0c;这仍然不能使它完美无缺…

048:利用vue-video-player播放m3u8

第048个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

MyBatis进阶之分页和延迟加载

文章目录 分页1. RowBounds 分页2. PageHelper 分页3. PageInfo 对象属性描述 延迟加载立即加载激进式延迟加载真-延迟加载 分页 Mybatis 中实现分页功能有 3 种途径&#xff1a; RowBounds 分页&#xff08;不建议使用&#xff09;Example 分页&#xff08;简单情况可用)Pag…

关于对向量检索研究的一些学习资料整理

官方学习资料 主要是的学习资料是&#xff0c; 官方文档 和官方博客。相关文章还是挺多 挺不错的 他们更新也比较及时。有最新的东西 都会更新出来。es scdn官方博客 这里简单列一些&#xff0c;还有一些其他的&#xff0c;大家自己感兴趣去看。 什么是向量数据库 Elasticse…

文件加密软件哪个最好用 好用的文件加密软件推荐

一说到文件加密软件&#xff0c;可能大家都会去搜一些不知名的软件来&#xff0c;但是选择这种加密软件&#xff0c;最好还是要看一些资质的。 资质不好的&#xff0c;可能加密过后你自己也打不开文件&#xff0c;&#xff08;ps&#xff1a;我自己就遇到过这种情况&#xff09…

基于Java SSM框架高校校园点餐订餐系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架高校校园点餐订餐系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&a…

Oracle(2-14)User-Managed Incomplete Recovery

文章目录 一、基础知识1、Incomplete Recovery Overview 不完全恢复概述2、Situations Requiring IR 需要不完全恢复的情况3、Types of IR 不完全恢复的类型4、IR Guidelines 不完全恢复指南5、User-Managed Procedures 用户管理程序6、RECOVER Command Overview 恢复命令概述7…

Python数据科学视频讲解:Python注释

2.3 Python注释 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解2.3节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵盖数据科学应用的全流程&#xff0c;包括数据科学应用和…

20231210原始编译NanoPC-T4(RK3399)开发板的Android10的SDK

20231210原始编译NanoPC-T4(RK3399)开发板的Android10的SDK 2023/12/10 17:27 rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ mkdir nanopc-t4 rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ cd nanopc-t4/ …

【AIE】AIE微信合集

AIE微信合集 AIE(1) 对于Versal&#xff0c;我们从系统角度看&#xff0c;可将其分为3个Domain&#xff1a;AIE、PS和PL&#xff0c;如下图所示。如果要运行一个AIE的应用&#xff0c;绝大多数情况下&#xff0c;这3个Domain我们都会用到&#xff0c;使其协同工作。这里我们仅…

《绝地求生》新手怎么玩 游戏基本介绍

随着电竞热潮的兴起&#xff0c;《绝地求生》已经成为了一款备受玩家热爱的游戏。这款游戏在全球范围内拥有庞大的玩家群体&#xff0c;它将你置身于一个荒无人烟的岛屿上&#xff0c;与其他99名玩家展开生死竞争。作为一个新手&#xff0c;下面闲游盒小盒子就为大家详细介绍一…