文章目录

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

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

什么是代理模式

一. 代理模式简介

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

  • 定义:为其他对象提供一种代理,以控制对这个对象的访问。
    可以理解为:在访问对象时引入一定程度的间接性,由这种间接性来附加多种用途
  • 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;}
}

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

  1. 【设计模式】代理模式之JDK动态代理与CGLIb代理区别

    一.什么是代理? 代理模式是Java中常见的一种模式,英文名字叫走Proxy或者Surrogate,代理的本意是一个人代表另一个人,或者一个机构代表另一个机构,采取行动,因而,代理和现实生活中的中介有 ...

  2. 设计模式(十三) 代理模式和Java动态代理

    Proxy Pattern 1. 什么是代理模式 代理模式: 给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问. Proxy Pattern: Provide a surrogate ...

  3. 代理模式之详谈动态代理模式(Spring的AOP实现)

    java动态代理实现与原理详细分析 1.代理模式 关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 代理 ...

  4. 代理模式及JDK动态代理(InvocationHandler)的简单实现与分析

    在慕课网上学习了讲解代理模式的一个课程--<模式的秘密--代理模式>,感叹于David老师屌炸天的PPT,同时,老师一步一步模仿JDK源码去写code,教我们去简单实现JDK中的动态代理, ...

  5. 代理模式之jdk动态代理的实现

    学习动态代理之前需要了解静态代理 并且牢记静态代理的缺点 //首先被代理的类需要实现一个接口 public interface ProxyInterface {public void say(Stri ...

  6. 代理模式 、JDK动态代理、cglib动态代理

    代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢? 因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思. 再如我 ...

  7. 【学习笔记】ABAP OOD设计模式 - 桥接模式

    ABAP OOD设计模式 - 桥接模式 整理转自-<SAP ABAP 面向对象程序设计(原则.模式及实践)> 桥接模式又称为桥梁模式,在程序开发中,采用不同的维度分解一系列对象,然后采用组 ...

  8. 代理模式中的动态代理

    动态代理和静态对比基本思路是一致的,只不过动态代理功能更加强大,随着业务的扩展适应性更强.如果还以找对象为例,使用动态代理相当于是能够适应复杂的业务场景.不仅仅只是父亲给儿子找对象,如果找对象这项业务 ...

  9. 代理模式之Java动态代理

    2019独角兽企业重金招聘Python工程师标准>>> 1. Overview Java在java.lang.reflect包下,定义了自己的代理.利用这个包下的类,我们可以在运行时 ...

最新文章

  1. java表或视图不存在_Error querying database. Cause: java.sql.SQLSyntaxErrorException: ORA-00942: 表或视图不存在...
  2. Soul网关发布2.2.0:让高性能网关变得如此简单!
  3. 7.MATLAB变量——矩阵操作二
  4. Intellij Idea/Webstorm/Phpstorm 的高效快捷键
  5. C语言加取址符的作用,C语言中指针和取地址符的关系
  6. 解决错误:Re-installation failed due to different application signatures
  7. 用c#开发微信 (13) 微统计 - 阅读分享统计系统 3 UI设计及后台处理
  8. javaScript命名规范
  9. 【第二组】项目冲刺(Alpha版本)第三次每日例会 2017/7/13
  10. Python:pathlib库使用方法
  11. CSS的继承层叠和特殊性 样式的继承和优先级属性
  12. Python 源码剖析 目录
  13. 二本学院计算机专业的考研er如何顺利上岸?
  14. time stamp convert
  15. mkv文件怎样转成mp4
  16. 随机过程之基本概念(一)
  17. java毕业设计菜鸟驿站快递分发系统Mybatis+系统+数据库+调试部署
  18. 租服务器的 直连100m是啥,如何知道我的服务器带宽是独享10M或者100M?
  19. 20P42 500个LUTs创意旅行VLOG时尚婚礼人物环境复古特殊INS电影调色预设+25个复古老电影VHS特效
  20. mysql中常用的筛查语句,使用SQL语句进行数据筛选的方法

热门文章

  1. python爬取网页新闻_Python爬取新闻网数据
  2. php 实时监测网站是否异常_网站跳转劫持解决,网站跳转劫持解决方法只有3步...
  3. linux的exec函数
  4. Android之智能问答机器人
  5. JS 逆向 --- 过无限debugge、hook、js混淆还原、控制流混淆
  6. 并查集算法c语言版,并查集及其C程序实现.doc
  7. 外设驱动库开发笔记39:按键操作驱动
  8. PID控制器开发笔记之八:带死区的PID控制器的实现
  9. SpringMVC解决静态资源不能访问
  10. 无限超越超级机器人nds_阿里重新定义个人电脑!仅名片大小,无限升级,不怕丢失无惧病毒,价格仅传统PC一半...