分析代理模式

学过设计模式,用过设计模式,但是转瞬又忘了,这些模式到底是什么,到底是干什么用,到底是用在哪里的.看DRP的时候,又介绍了代理模式,介绍了静态代理,动态代理;当时就觉得代理模式,就像是在客户端和真实的主题类中加了一个隔层,就像是解耦,加了一个中间层.

之前学习的时候,感觉那个例子举得不好,我一直不明白为什么要用代理.他的例子说了一个人小明要追小美,但是小明拜托小代去帮忙追小美,给小美送礼物,最后小美喜欢上小代了.当时觉得,小明个二货,追人还要找代理,最后人财两空.其实,完全可以不用代理,自己出马的.

后来发现,代理,现实中很多都需要用到代理的,有的甚至是必须使用代理.比如明星,你要找他们办事,他们就会让你去找他的经纪人,经纪人就是代理;打官司,需要律师,律师就是代理;你家生产了很多产品,但是不想自己去卖,交由销售商去卖,销售商就是代理;还有上网翻墙的时候,使用代理,可以使用静态代理,你明确的指定任意一个,或者使用动态代理,他自己决定用哪个,你不管,只要能上网就成.所以说,代理的运用是相当广泛的.

那个时候学习的代理模式,类图就是如下所示.有一个客户端,一个接口Subject,接口中有一个方法request().还有两个类,代理类和实际对象类来实现这个接口,这样他们就有共同的行为了,可以在任何使用实际对象类的地方使用代理了.

如之前的小明追小美.小明是RealSubject,小吕是ProxySubject,而送礼物是Subject的接口,里面的request()方法可以是送各种东西.那么由于小明和小代都实现了送礼物的接口,所以里面的送各种礼物的方法他们都有.所以,都可以给小美送礼物.而由于小代是代理小明去送礼物的,所以实际小代送给小美的礼物,都是从小明那里拿的.送给小美的任何礼物都是小明要送给小美的.

其实代理模式除了能提供代替功能,还可以提供一些附加功能.如在学习DRP的时候,分析了静态代理和动态代理.他介绍了你可以在代理模式的代理类中添加打印信息,在调用打印前,在调用后打印,调用成功打印,这样就可以添加日志记录的功能,而不影响他们实际的类.这就可以做到对修改关闭,对添加开放.

就如下图的时序图显示的,在客户端调用代理的addUser()方法,代理的该方法可以打印输入参数,然后再去调用实际对象的addUser()方法,然后在添加完成之后打印成功失败信息,最后返回结果.你在代理类中还可以做很多事,而实际对象类只要写最关键的addUser()的代码,其他不用管.这也是单一职责的体现.

但是就如同图中所说的,这样的代理虽然很有好处,但是一个实际对象类对应一个代理类,那么类就太多了.而且这些代理类的方法可能会大量重复,而重复的代码最好不要出现多次.所以一个好的方法就是把这些重复的方法,提取出来,可以试试用泛型.

但是实际Java他们已经考虑到这个问题,所以提供了动态代理.

动态代理的类图是这样的,他和静态代理的类图的区别就是图中的Proxy已经不是我们自己写的一个代理类了,而是java他自己提供的一个Proxy类,他是动态代理类.你可以根据实际对象类的情况,用Proxy的静态方法newProxyInstance()获得相应的实际对象的代理,所以这个代理类代理的是哪个类,只有在运行的时候才能知道.

所以在实际对象类和代理中,他们没有直接的关系了,不用代理再指向实际对象.而他们之间的关系由InvocationHandler(调用处理器)来维护,而这个InvocationHandler的类必须实现InvocationHandler的接口.只要实现了这个接口,类名爱叫啥叫啥.

而为什么InvocationHandler来维护他们的关系,他有什么优势?InvocationHandler的作用是响应代理的任何调用.当客户端调用代理的时候,代理就会找InvocationHandler,要他去实现客户端的请求,而InvocationHandler调用的Invoke方法,再去调用实际对象类的实际方法.

注意InvocationHandler的invoke方法,不管你Proxy动态代理类被调用的是什么方法,对于调用处理器他被调用的只有invoke.以不变应万变,不管你来的是什么对我来说都是invoke,我统一处理了就好.

再看一下动态代理的时序图,下图中的jdk代理类就是上图中的Proxy,而LogHandler对象就是InvocationHandler,UserManageImpl就是RealSubject.

客户端调用jdk代理类的findUserById()方法,而代理立马调用LogHandler的invoke方法,在invoke方法中也和之前一样打印了一些信息,并且调用了实际对象的findUserById()方法,来返回实际的结果.

两幅时序图的区别就是,中间原本的UserManagerImplProxy的代理类被jdk代理类和LogHandler替换了.在静态代理中,需要明确指明代理类是谁,代理的是哪个实际对象类;而在动态代理类中的,则用jdk代理类和LogHandler,来根据实际情况来得到实际的代理类.

jdk代理类可以根据传递过来的参数生成对应的代理,而生成的代理,会有实际对象的所有方法,你调用这些方法的任意方法,都会去找LogHandler的invoke()方法,而invoke方法的参数也会告诉他,他要去找哪个类,找哪个方法,用哪些参数,然后就可以动态的调用方法了

这样就只用一份代码,可以创建所有需要的代理类.

写完了,觉得还是不大了解,只有真正了解,才能真正正确的运用.最后总结一下,用静态代理,符合了单一职责,和开放封闭原则,但是代理类太多,代码重复;动态代理,解决了这些问题,只用一份代码,就可以创建无数代理类,缺点是效率低.而且代理模式可以使RealSubject类中的方法的功能更单一,因为用代理,可以将与功能无关的代码都写到invoke方法中,那么以后要维护RealSubject类也是很方便的.

分析代理模式,布布扣,bubuko.com

时间: 2024-10-12 17:32:24

分析代理模式的相关文章

Android源码代理模式---Binder

Binder是Android的进程间通信核心,如果看过Android源码,你会发现源码中Android的各种核心服务都是通过Binder机制进行相互通信的.在Binder的client部分就是通过代理模式来访问Server端的.这里想通过代理模式来详细介绍Java层Binder.文中会简单介绍代理模式,详细介绍Binder机制.(源码基于6.0.1) 代理模式 意图 对其他对象提供一种代理以控制对这个对象的访问. UML图 代码示例 abstract class Subject{ public

JStorm与Storm源码分析(五)--SpoutOutputCollector与代理模式

本文主要是解析SpoutOutputCollector源码,顺便分析该类中所涉及的设计模式–代理模式. 首先介绍一下Spout输出收集器接口–ISpoutOutputCollector,该接口主要声明了以下3个抽象方法用来约束ISpoutOutputCollector的实现类.接口定义与方法说明如下: /** * ISpoutOutputCollector:Spout输出收集器接口 */ public interface ISpoutOutputCollector { /** * 改方法用来向外

Java设计模式-代理模式之动态代理(附源码分析)

Java设计模式-代理模式之动态代理(附源码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的区别就是:动态代理是在运行时刻动态的创建出代理类及其对象.上篇中的静态代理是在编译的时候就确定了代理类具体类型,如果有多个类需要代理,那么就得创建多个.还有一点,如果Subject中新增了一个方法,那么对应的实现接口的类中也要相应的实习该方法,不符合设计模式原则. 动态代理的做法:在运行时刻,可以动态创建出一个实现了多个接口的代理类.每个代理类的对象都会关联一个表示内部处理

Java设计模式-代理模式之动态代理(附源代码分析)

Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代理是在编译的时候就确定了代理类详细类型.假设有多个类须要代理.那么就得创建多个. 另一点,假设Subject中新增了一个方法,那么相应的实现接口的类中也要相应的实现这些方法. 动态代理的做法:在执行时刻.能够动态创建出一个实现了多个接口的代理类.每一个代理类的对象都会关联一个表示内部处理逻辑的Inv

动态代理模式--源码分析

Proxy源码 1,成员变量 ?代理类的构造函数参数.默认每个代理类都具有一个invocationHandler的构造方法.(本文代码主要基于jdk 1.7) /** parameter types of a proxy class constructor */ private static final Class<?>[] constructorParams = { InvocationHandler.class }; ?缓存代理对象. private static final WeakCa

Android知识体系梳理笔记三:动态代理模式---插件加载机制学习笔记

静态代理模式 静态代理模式就是我们常说的代理设计模式,我们采用一个代理类调用原有的方法,且对产生的结果进行控制:举个例子:我们现在在玩一款网络游戏,需要打怪升级:太累就找个代理吧,一觉醒来就会发现我们已经当上CEO,迎娶白富美,天下第一了! 本来我们只能打怪,打怪-,但经过代理类增强,我们不仅可以打怪,还可以升级拿装备.就这样子了! 上代码: * 同一功能接口 public interface PlayNetGame { String beatMonster(); } 1 2 3 4 1 2 3

【设计模式】-代理模式

模式动机 在某些情况下,一个客户不想或者不能直接引用一个对 象,此时可以通过一个称之为"代理"的第三者来实现 间接引用.代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务. 通过引入一个新的对象(如小图片和远程代理 对象)来实现对真实对象的操作或者将新的对 象作为真实对象的一个替身,这种实现机制即 为代理模式,通过引入代理对象来间接访问一 个对象,这就是代理模式的模式动机. 模式定义 代理模式(Proxy P

JAVA设计模式之代理模式

学编程吧JAVA设计模式之代理模式发布了,欢迎通过xuebiancheng8.com来访问 一.概述 给某一个对象提供一个代理,并由代理对象来完成对原对象的访问.代理模式是一种对象结构型模式. 二.适用场景 当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口. 三.UML类图 四.参与者 1.接口类:Subject 它声明了真实访问者和代理访问者的共同接口,客户端通常需要针对接口角色进行编程. 2.代理类

java 动态代理模式

一.相关类及其方法:java.lang.reflect.Proxy,Proxy 提供用于创建动态代理类和实例的静态方法.newProxyInstance()返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序(详见api文档) java.lang.reflect.InvocationHandler,InvocationHandler 是代理实例的调用处理程序 实现的接口.invoke()在代理实例上处理方法调用并返回结果.在与方法关联的代理实例上调用方法时,将在调用处理程序