找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 155533|回复: 0

程序员内功心法【设计模式】之代理模式

[复制链接]

该用户从未签到

发表于 2020-5-17 22:26:59 | 显示全部楼层 |阅读模式

您需要 登录 才可以下载或查看,没有账号?立即注册

×
基本定义

[list,
[*,代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引用。
[*,在代理模式中,“第三者”代理主要是起到一个中介的作用,它连接客户端和目标对象。
[/list,模式结构
[list,
[*,Subject: 抽象角色。声明真实对象和代理对象的共同接口。
[*,Proxy:代理角色。代理对象与真实对象实现相同的接口,所以它能够在任何时刻都能够代理真实对象。代理角色内部包含有对真实对象的引用,所以她可以操作真实对象,同时也可以附加其他的操作,相当于对真实对象进行封装。
[*,RealSubject :真实角色。它代表着真实对象,是我们最终要引用的对象。
[/list,

                               
登录/注册后可看大图

模式实现我们有多种不同的方式来实现代理。如果按照代理创建的时期来进行分类的话, 可以分为两种:静态代理、动态代理。
静态代理
[list,
[*,是由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类.class文件就已经被创建了。
[*,优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展。
[*,缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。
[/list,代码实现
[list,
[*,Subject 抽象角色
[/list,
[list,
[*,RealSubject 抽象实现类
[/list,@Slf4jpublicclassBuyHouseImplimplementsBuyHouse{@OverridepublicvoidbuyHouse{log.info("RealSubject 买房");}}
[list,
[*,Proxy 代理类 (1.继承于抽象类, 2.关联真实实现类)
[/list,@Slf4jpublicclassBuyHouseProxyimplementsBuyHouse{BuyHouse buyHouse;publicBuyHouseProxy(BuyHouse buyHouse){this.buyHouse = buyHouse;}@Overridelog.info("选择房源");log.info("洽谈价格");buyHouse.buyHouse;log.info("最终成交");}}
[list,
[*,Client 代理模式测试类
[/list,@Slf4jpublicclassStaticProxyTest{publicstaticvoidmain(String args){BuyHouse buyHouse =newBuyHouseImpl;log.info("静态代理后> ");BuyHouseProxy proxy =newBuyHouseProxy(buyHouse);proxy.buyHouse;}}
[list,
[*,输出结果
[/list,RealSubject 买房
静态代理后>
选择房源
洽谈价格
RealSubject 买房
最终成交
动态代理

[list,
[*,是在程序运行时通过反射机制动态创建的
[*,相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度。但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持interface代理的桎梏,因为它的设计注定了这个遗憾。
[/list,代码实现
[list,
[*,Proxy 动态代理, 实现InvocationHandler接口
[/list,@Slf4jpublicclassDynamicProxyimplementsInvocationHandler{//代理类需要关联我们真实角色Objectobject;publicDynamicProxy(Objectobject) {this.object=object;}@OverridepublicObject invoke(Object proxy, Method method, Object args) throws Throwable {//通过反射调用真实方法Object result = method.invoke(object, args);log.info("最终成交");returnresult;}}
[list,
[*,Client 动态类测试类
[/list,publicclassDynamicProxyTest{//真实角色/*** ClassLoader loader,* Class<?> interfaces,* invocationHandler h*/BuyHouse proxy = (BuyHouse) Proxy.newProxyInstance(BuyHouse.class.getClassLoader,newClass{BuyHouse.class},newDynamicProxy(buyHouse));
[list,
[*,输出结果
[/list,选择房源
洽谈价格
RealSubject 买房
最终成交
优点
[list,
[*,代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
[*,代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的。
[*,代理对象可以扩展目标对象的功能
[/list,缺点
[list,
[*,由于在客户端和真实主题之间增加了代理对象,会造成请求的处理速度变慢。
[*,增加了系统的复杂度
[/list,使用场景
[list,
[*,远程代理:为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
[*,虚拟代理:通过使用过一个小的对象代理一个大对象。这样就可以减少系统的开销。
[*,保护代理:用来控制对真实对象的访问权限。
[/list,总结
[list,
[*,代理模式是通过使用引用代理对象来访问真实对象,在这里代理对象充当用于连接客户端和真实对象的中介者。
[*,代理模式主要用于远程代理、虚拟代理和保护代理。其中保护代理可以进行访问权限控制。
[/list,JDK源码
[list,
[*,java.lang.reflect.Proxy
[/list,publicclassProxyimplementsjava.io.Serializable{publicstaticObjectnewProxyInstance(ClassLoader loader,Class<?> interfaces,InvocationHandler h)throwsIllegalArgumentException{Objects.requireNonNull(h);finalClass<?> intfs = interfaces.clone;finalSecurityManager sm = System.getSecurityManager;if(sm !=null) {checkProxyAccess(Reflection.getCallerClass, loader, intfs);}/** Look up or generate the designated proxy class.*///1. 查找或生成指定的代理类Class<?> cl = getProxyClass0(loader, intfs);/** Invoke its constructor with the designated invocation handler.*/try{if(sm !=null) {checkNewProxyPermission(Reflection.getCallerClass, cl);}//2. 根据Class获取构造器finalConstructor<?> cons = cl.getConstructor(constructorParams);finalInvocationHandler ih = h;if(!Modifier.isPublic(cl.getModifiers)) {AccessController.doPrivileged(newPrivilegedAction<Void> {publicVoidrun{cons.setAccessible(true);returnnull;}});}// 3. 返回实例化的构造器returncons.newInstance(newObject{h});}catch(IllegalAccessException|InstantiationException e) {thrownewInternalError(e.toString, e);}catch(InvocationTargetException e) {Throwable t = e.getCause;if(tinstanceofRuntimeException) {throw(RuntimeException) t;}else{thrownewInternalError(t.toString, t);}}catch(NoSuchMethodException e) {}}}
回复

使用道具 举报

网站地图|页面地图|文字地图|Archiver|手机版|小黑屋|找资源 |网站地图

GMT+8, 2024-11-28 14:47

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表