【学习笔记】结合代码理解设计模式 —— 代理模式(静态代理、动态代理、延伸)

文章目录

  • 什么是代理模式
      • 一. 代理模式简介
      • 二. 静态代理模式
      • 三. 动态代理模式
          • 万能模版

前言:笔记基于狂神设计模式视频、《大话设计模式》观后而写
(最近一直在更新之前的刷题博客,今天久违地更新一篇新博客啦~)

什么是代理模式

一. 代理模式简介

代理模式是很常用的设计模式噢~同时也有很多的类型,适当学习一下是非常有必要的!

  • 定义:为其他对象提供一种代理,以控制对这个对象的访问。
    可以理解为:在访问对象时引入一定程度的间接性,由这种间接性来附加多种用途
  • UML 图:代理组合真实角色,代理和真实对色都继承公共接口
    在这里插入图片描述
  • 举个例子:经纪人(代理)、明星(真实角色),都继承“接戏”接口。想找明星演戏的话,就得通过经纪人的“接戏”(把明星想象成经纪人的私有化对象)。这样做的话,经纪人可以在自己的“接戏”方法上添加筛选、谈薪等任务,而明星只需关注自己的业务即可。
  • 在上面这个例子里,代理模式的好处就有体现出来了。真实角色更加地专一,并且在代理角色的拓展,也遵守了OOP原则的开放封闭原则
  • 代理模式的分类
    1. 静态代理
    2. 动态代理(这两种类型,下文有结合代码使用、讲解)
    3. 远程代理:为一个对象在不同地址空间提供局部代表,用于隐藏一个对象存在于不同地址空间的事实(比如调用另一台PC的方法)
    4. 虚拟代理:用于存放实例化需要很长时间的真实对象,可以达到性能的最优化。比如打开哔哩哔哩,卡顿情况先显示文字,而图片、视频流可能就只是一个白框之类的玩意,之后再逐渐加载出来,这里就用到了虚拟代理
    5. 安全代理、智能指引等其他分类,感兴趣可以去查查~

二. 静态代理模式

  • 角色分类
    1. 抽象角色:接口 or 抽象类。
    2. 真实角色:就被代理的角色
    3. 代理角色:真实角色的代理,一般会加一些附属操作。
    4. 客户:访问代理角色的人。
  • 好处:
    1. 使真实角色的操作更加纯粹,不用关注一些公共的业务。
    2. 公共业务交给代理角色,实现了业务的分工
    3. 公共业务发生拓展的时候,方便管理
  • 缺点:一个真实角色对应一个代理角色,代码量增大,效率变低
  • 样例代码:房东、中介、客户、租房(试着想想对应上面的什么角色吧~)
// ps:public class 不要介意,这里我是把不同文件的代码直接拷过来了。
// 1. 公共接口
public interface Rent {public void rent();
}// 2. 房东(真实角色)
public class Host implements Rent{@Overridepublic void rent() {System.out.println("房东:要出租房子");}
}// 3. 中介(代理角色)
public class MyProxy implements Rent {// 采用"组合"方式private Host host;MyProxy() {}MyProxy(Host host) {this.host = host;}@Overridepublic void rent() {// 可以添加一些更多的内容,而主体(被代理类)却不用关心这些事情,只需要做好自己的事即可。// 满足开放封闭原则System.out.println("中介:带着看房");host.rent();System.out.println("中介:签合同");}
}// 4. 客户:访问代理角色
public class Client {public static void main(String[] args) {// 只需要找中介即可,不用管房东Host host = new Host();MyProxy MyProxy = new MyProxy(host);MyProxy.rent();}
}

三. 动态代理模式

为了解决上面静态代理模式的缺点,这里又有了动态代理模式~
(这一块不太好理解,我写得估计也不太详细,建议再看一下视频、或者其他博客)

  • 原理:动态代理基于反射机制实现。
  • 和静态代理的区别
    1. 静态代理:实现接口,再通过接口实现类的实例来代理。
    2. 动态代理:通过反射,造出一个接口类的实例
      (再原理一点,就是通过反射先造出一个带构造方法的,接口的克隆体,再通过这个克隆体的构造方法,生成接口实例)
  • 使用到的类:
    1. Proxy:提供用于创建动态代理类和实例的静态方法,生成一个
    2. InvocationHandler:每个代理实例都具有一个关联的调用处理程序,调用代理实例的方法时,会被指派到其调用处理程序的 invoke 方法上。
    3. com.sun.proxy.$Proxy0 :由 Proxy::newProxyInstance() 生成的代理类。实现了传入接口的每一个方法,以及Object方法。并且统一调用了InvocationHandler 的 invoke() 方法。
  • 好处
    1. 静态代理的好处
    2. 一个动态代理类代理的是一个接口,一般就是对应的一类业务。规避了静态代理的缺点
    3. 在原始类和接口未知时,就确定代理类的代理行为。灵活。
  • 样例代码:还是房东中介的例子噢
// 继承 InvocationHandler 接口,此时 this 就是一个 InvocationHandler
public class ProxyInvocationHandler implements InvocationHandler {// 被代理的接口private Rent rent;public void setRent(Rent rent) {this.rent = rent;}// 生成代理类public Object getMyProxy() {return Proxy.newProxyInstance(rent.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);}// InvocationHandler 对应的方法 invoke,用于处理代理实例,并且返回结果。被 $Proxy0 的方法调用@Overridepublic Object invoke(Object Proxy, Method method, Object[] args) throws Throwable {// Method 也是反射包下的类,和反射相关。System.out.println("动态代理来了噢!");Object res = method.invoke(rent, args);return res;}
}public class Client {public static void main(String[] args) {// 只需要找中介即可,不用管房东Host host = new Host();ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();// 放入被代理对象proxyInvocationHandler.setRent(host);Rent proxy = (Rent)proxyInvocationHandler.getMyProxy();// 这里的 rent,之后会执行 invoke(此时参数 Method 就是 rent)// “代理对象”执行“接口方法”,然后指派到对应的 InvocationHandler 的 invoke 上proxy.rent();}
}
  • 整理:无注释,一个文件不到30行,写完整个动态代理例子
public interface Rent {void rent();
}public class RentDynamicProxy implements InvocationHandler {Rent rent;RentDynamicProxy(Rent rent) {this.rent = rent;}Object getProxy() {return Proxy.newProxyInstance(rent.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("启用动态代理");return method.invoke(rent, args);}
}public class Host implements Rent{@Overridepublic void rent() {System.out.println("房东出租");}public static void main(String[] args) {Host host = new Host();RentDynamicProxy rentDynamicProxy = new RentDynamicProxy(host);Rent proxy = (Rent)rentDynamicProxy.getProxy();proxy.rent();}
}
万能模版
  • 任何接口都可以用噢
public class BetterProxyInvocationHandler implements InvocationHandler {// 1. 被代理的接口private Object target;// 设置被代理的接口public void setTarget(Object target) {this.target = target;}// 2. 生成得到代理类public Object getProxy() {return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("执行了 " + method.getName() + " 方法");Object res = method.invoke(target, args);return res;}
}

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

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

相关文章

js 正则 长度不超过50_如何花不超过50元人民币,拍抖音网红海马体照片?

前段时间,抖音上的海马体-网红照一夜间爆发!火了!海马体照相馆又一次被推上了时尚潮流的打卡风口,深受年轻群体的青睐。其中当然也包括我~这个风我还是特别想要跟一波的。但是想必大家都知道,海马体照相馆生意一直火爆…

多核处理器_英特尔十代酷睿i5-10400大战R5 3600,到底谁是千元处理器一霸?

Hello大家好,我是兼容机之家的小牛。要说英特尔十代酷睿中最走量的处理器,莫过于i5 10400这颗千元神U了。最近我们兼容机之家推出了几款搭载i5 10400等十代酷睿CPU的主机,性价比非常不错,小伙伴可以翻看一下我们往期的文章。今天就…

项目日报模板_第一届全国技能大赛现场直击:混凝土建筑项目全场最“高”

大洋网讯 混凝土建筑项目的比赛场馆位于室外,高达12米,让这个项目成为全场最“高”项目。“在现代化大型工地,都是用泵车浇灌混凝土,我们这里比赛也模拟了这一个工地的现实场景,让选手使用泵车浇灌混凝土。泵车的手臂要…

【LeetCode笔记】51. N 皇后(DFS、经典题)

文章目录题目描述思路 && 代码题目描述 经典题了…但是大一敲过后就再没碰过了。结果面试还是会问 ,今天补一下~ 思路 && 代码 还是挺清晰的,要点如下: 使用 DFS,找到一个了再继续找对每一行&…

表格c1等于a1加b1_中国最牛驾照,C1、B1、B2、A1、A2随便开,被称为万能的驾照!...

导读:中国最牛驾照,C1、B1、B2、A1、A2随便开,被称为万能的驾照!现在社会上的汽车越来越多了,而车主们,想要行车上路,除了要有车,还要有一样必须的东西,那就是驾照。驾照…

【LeetCode笔记】117.填充每个节点的下一个右侧节点指针 II(二叉树、DFS)

文章目录题目描述思路 && 代码题目描述 很烦…面试被这题干碎了,赶紧给查漏补缺一波! 思路 && 代码 主要思路:先右,再左(因为左边依赖右边!)getNext():当前节点…

r720支持多少频率的内存吗_电脑基础知识:内存条知识大全,看完小学生都了解...

一、基础知识如果你不了解内存条,如果你只知道内存容量越大越好,如果你想更加了解内存条,不妨来看看这里,今天给大家分享那些最简单也是最容易理解的内存条知识。1、定义、作用内存条又叫随机存取存储器,是一种存储技术…

关键词堆砌生成器_网络推广软件的使用和24种关键词挖掘方法

第398-399期网络推广学习,主讲课程:推广软件的使用和24种关键词的挖掘方法。具体内容如下:一、商务卫士(宣传易)主要的功能:1.商情推广2,产品添加(20个以上)3.百宝箱>…

【LeetCode笔记】299. 猜数字游戏 (Java、偏数学)

文章目录题目描述思路 && 代码题目描述 顶级阅读题!今天的每日一题,感觉评论区大佬的写法挺值得记录的,就又水了一篇答题文~ 思路 && 代码 O(n)、O(1)核心代码:Case 2 的两个 if 处理,…

currenthashmap如何实现线程安全_什么是多线程?如何实现多线程?

什么是进程?电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。比如下图中的QQ、酷狗播放器、电脑管家等等。什么是线程?进程想要执行任务就需要依赖线程。换句话说,就是进程中的…

【LeetCode笔记 - 每日一题】375. 猜数字游戏 II (Java、DFS、动态规划)

文章目录题目描述思路 && 代码DFS动态规划新系列~用于区分开高频题和每日一题~ 题目描述 一眼二分,但是实际上并不是这题让我想到社团的猜数字游戏…但是给钱是真过分了 思路 && 代码 DFS 自底向上进行递归。Math.max(…

【LeetCode笔记 - 每日一题】318. 最大单词长度乘积(Java、位运算)

文章目录题目描述思路 && 代码题目描述 挺不错!有bitmap的感觉了。 思路 && 代码 思路好想:两两对比,无公共判断,维护 res那么,如何进行公共判断?这个是主要的问题给每个字符串&#x…

技术交底软件_【干货分享】软件类产品如何进行专利挖掘与技术交底书撰写?...

“导读:在很多人的认知里,软件著作权是软件著作权,专利是专利,两者并没有太多关联。甚至有的人认为,软件产品只能申请软件著作权保护,不能申请专利保护。但是,当有人抄袭你的软件设计理念&#…

【LeetCode笔记 - 每日一题】384. 打乱数组(Java、洗牌算法)

文章目录题目描述思路 && 代码题目描述 中等题,很赞!第一次碰到涉及洗牌算法的题有点涉及概率,主要是要实现公平的随机 思路 && 代码 采用了 Knuth 洗牌算法,可以看看这篇博客时间复杂度O(N),空间…

【LeetCode笔记 - 每日一题】423. 从英文中重建数字(Java、字符串、偏思路)

文章目录题目描述思路 && 代码题目描述 看了题目以后想到啥? 字符数量统计银行家算法逐个拆解建立数字 - 字符串的全局映射 思路 && 代码 抄答案了,采取了评论区三叶dalao的写法(不得不说,人家的处理写法是真…

字符串的地址_面试题:我有一批IPv6地址,你帮我想个办法来存储?

作者:dadiyang-绪扬来源:公众号Java面试那些事儿之前写了一篇《面试题:请用代码实现ip地址与int之间互换?》,有读者评论问到 IPv6 的转换方法,于是抽时间也自己实现了一下。面试官:我有一批IPv6…

【LeetCode笔记 - 每日一题】519. 随机翻转矩阵(Java、随机、双指针)

文章目录题目描述思路 && 代码题目描述 又是涉及到均等概率的随机~ 思路 && 代码 用的题解区三叶的代码~写得是真的好!不论题目,但抄一遍代码都能觉得有收获!维度转化:并没有创造二维数…

当前操作系统缺少黑体等字体_从零开始开发一个操作系统

在2019年的最后一天终于完成了整个系统的开发,并给它起名曰——Inios 。就如同文章名字一样,完全是从内核编写,非二次开发,从最初的“hello os”到初次有了系统的样子。主要用C语言编写,部分汇编语言。。整个操作系统完…

db设计专用excel_独家|自卸车如何实现侧板结构快速设计,减少重复工作?

作者| 张凯 汉阳专用汽车研究所科研技术部工程师 主要从事专用汽车产品结构仿真与轻量化随着城市发展的步伐不断加快,适用于各种工况的自卸车、城市渣土车市场需求量不断增大。目前市场自卸车车厢主要有两种:U型车厢和普通矩形车厢。其中U型车厢自卸车&a…

python 线程退出_python线程退出

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元!如果某线程并未使用很多 io 操作, 它会在自己的时间片内一直占用处理器(和 gil)。 也就是说&…