题记:
关于这篇文章,我想说,写的很好,浅显易懂,如果你刚好要用到这个模式,此文章绝对会助你一臂之力!
如果说看完设计模式之后,哪个模式最让我印象深刻和半醉半醒,那一定就是代理模式(Proxy)。代理模式看似非常简单,很直接,应用的也很广泛,然而,放下书,去使用的时候,可能是由于动态代理和远程代理实现的细节还没弄清,忽然发现,代理模式究竟为哪般还是模糊的。此处记录和总结下我所理解的代理模式,本部分主要是基础部分。
1 面向对象设计之路---使用面向对象设计原则
1.1 初始设计
学习程序设计,还是以程序的语言来说吧:
我们有一个接口Callable:
public interface Callable { public void call(); }
现在我们有一个实现类Phone:
public class Phone implements Callable { @Override public void call() { System.out.println("Phone is calling ..."); } //Other Phone methods }
OK,现在工作的很好,能完成要求的所有功能。
1.2 需求扩展
这时候,出现了一个新的需求,就是需要对Phone的所有动作进行计时,以对最终的收费提供依据,这时候有三种解决方案:
A 如果有源码,直接修改Phone类:一种可能的实现可能是如下形式:
public class Phone implements Callable { @Override public void call() { long startTime = System.currentTimeMillis(); System.out.println("Phone is calling ..."); long endTime = System.currentTimeMillis(); System.out.println("Call duration = " + (endTime - startTime)); } //Other Phone methods }
B不幸的是,我们没有源代码可以修改,可以采用继承的方式来解决:可能的实现如下:
public class Phone2 extends Phone { @Override public void call() { long startTime = System.currentTimeMillis(); super.call(); long endTime = System.currentTimeMillis(); System.out.println("Call duration = " + (endTime - startTime)); } }
C 除开A、B之外,我们还有一种方式来达到目的,那就是使用聚合来完成:示例如下
public class Phone3 implements Callable { private Callable phone; public Phone3(Callable phone) { this.phone = phone; } @Override public void call() { long startTime = System.currentTimeMillis(); phone.call(); long endTime = System.currentTimeMillis(); System.out.println("Call duration = " + (endTime - startTime)); } }
A、B、C三种方法对比,很容易发现:
A的做法最是糟糕,完全破坏了伟大程序员缔造伟大程序的美感,破坏了面向对象设计的第一大原则:开闭原则:软件实体应该对扩展开放,对修改关闭。OK,类似于A的做法以后不再出现了。
B的做法使用了面向对象语言里面的继承,相对于A来说,那是大大的进化了,也没有破坏开闭原则,但有一点,如果我们需要对Phone的call职责再加强一下,需要记录日志,那么采用继承的话,在Java中由于只支持单继承,因此需要再次从Phone2继承,容易造成类的爆炸,如此下去,会造成很多很多类和很长很长的继承链。
C的做法采用了对象聚合,在解决上述的新问题时,只需要再次聚合下Phone3就可以解决了,聚合比继承更好的优势主要体现在扩展性上,继承不够灵活,能更好的提高类的复用性。这也是面向对象设计的一大原则之一:合成/聚合复用原则:尽量使用合成/聚合,尽量不要使用继承。
仔细观察,聚合为什么会具有更强的能力呢,这里主要是在Phone3里面传入的是Callable接口,因此非常灵活,其实这是另外一个面向对象设计原则:依赖反转原则:要依赖于抽象,不要依赖与具体。另外一种说法是:要针对接口编程,不要针对实现编程。
2 代理模式的基本形式
代理,按其字面意义来说,就是指代替其他人做他们该做的事情,广泛的来讲,上述的继承和聚合方式实现都是代理的形式,继承中,子类将call的行为交给父类处理,聚合中,将具体的call行为交给引用的类处理。
在GoF提出的设计模式中,代理模式是这样定义的:
对其他对象提供一种代理以控制对这个对象的访问。
它的UML模型如下:
由此可见,代理与真实对象实现了同一个接口,对真实对象的请求事实上是通过代理来处理的。也可以说明前面所述的继承与聚合事实上也是一种代理。
3 代理模式的应用形式
远程代理:可以为一个不同的地址空间的对象提供一个局域代表对象;
虚拟代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建;
保护代理:基于访问权限可以控制对一个对象的访问;
…
4 代理模式的动态代理
上面所述的都属于静态代理,但代理模式的一大犀利之处就是其也能实现动态代理,即在运行时动态决定真实的被代理对象。
Java自身提供了实现动态代理的结构,自定义动态代理类,只需要使用java.lang.reflect包下面的InvocationHandler, Proxy和Method三个类就可以了,下面看一个简单的例子:
public class FirstInvocationHandler implements InvocationHandler { private Object o; public FirstInvocationHandler(Object phone) { this.o = phone; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Invoke start!"); method.invoke(o, args); System.out.println("Invoke completed!"); return null; } }
下面只需要调用就可以了,给个测试例子:
public class TestJavaProxy { public static void main(String[] args) { Phone phone = new Phone(); Callable proxyPhone = (Callable) Proxy.newProxyInstance(phone.getClass().getClassLoader(), phone.getClass().getInterfaces(), new FirstInvocationHandler(phone)); proxyPhone.call(); Date date = new Date(); Serializable proxyDate = (Serializable)Proxy.newProxyInstance(date.getClass().getClassLoader(), date.getClass().getInterfaces(), new FirstInvocationHandler(date)); proxyDate.toString(); } }
通过例子,将可以发现,我们可以自由实现我们需要的代理,只需要能传递正确的classLoader、interfaces和args,就能被代理到,这对于具有通用增强功能方法的尤其有意义,比如在典型的日志记录、事务管理、权限等控制上非常灵活。
5 代理模式的其他
本节主要论述代理模式中的一些应用,对JDK的动态代理也做了一些例子,关于更深层次的代理感触请查看下一节。
reference link:
http://www.linuxso.com/architecture/15869.html
分享到:
相关推荐
在这个"设计模式练习"中,我们主要关注的是Java编程语言中的设计模式应用。 首先,我们要了解设计模式的三大类别:创建型模式、结构型模式和行为型模式。创建型模式如单例(Singleton)、工厂方法(Factory Method...
关于设计模式,我有很多感触,Gof 的书我不知看了多少遍,可总是不太明白,我几年 没有使用C++了,里面的例子,看着很不爽。板桥先生网上的例子很简单明了,但是经过一 段时间的学习,有点不尽兴的感觉。于是又看...
设计色彩,色彩应用,色彩心理学,便于艺术或设计类专业用的教学资料
双感触装置的设计为触控屏带来了新的可能性,不仅增强了输入的精确度,也为多任务处理提供了更加灵活的方式。 首先,我们要理解双感触装置的核心概念。传统的触控屏通常只有一层传感器,用来检测单一的触摸输入。而...
本篇文章将详细探讨一种工程机械换挡感触器的设计原理、功能、工作过程以及其在实际应用中的重要性。 一、设计原理 换挡感触器是一种传感器,用于检测和传递工程机械换挡时的信号。它基于电磁感应或光电效应等原理...
我们可以从文件名“一种具有压感触控功能的显示装置.pdf”推测,这个文档很可能是详细的技术报告或专利描述,涵盖了压感触控显示装置的设计原理、工作方式、硬件结构、软件实现以及可能的优势和应用场景。...
总结来说,感触电子织物作为电子技术与传统制造业的深度融合,正在改变我们的生活方式。它不仅提升了产品的功能性,也预示着一个更加智能、互联的未来。随着更多行业对感触电子织物的关注和投入,我们有理由期待更多...
显示装置中应用压感触控技术,例如智能手机、平板电脑,甚至是智能电视和车载显示器,都可以提供更丰富、更具个性化的交互方式,提高人机交互的效率和满意度。随着科技的进步,压感触控技术有望在更多领域得到广泛...
"月光滟影·滟澜山别样中秋感触之夜"策划案是一个典型的高端房地产活动,旨在通过精心设计的体验提升品牌影响力,促进销售。这个案例展示了如何结合传统节日——中秋节,打造出一个具有深刻印象的品牌活动。 1. **...
它是数据科学的一部分,旨在揭示隐藏的模式、关联和趋势,以便用于商业智能、预测和决策支持。 【逻辑回归】 逻辑回归是一种广泛应用于分类问题的统计学习方法。它的全称为Logistic Regression,简称LR。尽管名字中...
乡村旅游中体验营销的应用:在乡村旅游中,体验营销可以帮助企业树立体验营销观念,提供乡村旅游服务的企业应从营销模式的角度来考虑解决方法,强调消费者的体验活动,以体验来衡量服务的质量优劣,提高消费者的感触...
本文将对测试小米手机后的感触进行详细叙述,旨在通过个人体验,从硬件性能、用户界面、市场定位以及与竞争对手的比较等方面,为读者提供一个全面的评价。 小米手机的硬件配置在同价位产品中属于佼佼者,搭载双核...
2.发扬设想力与制造力,应用多种东西、多种方式进展表示 五、评一评 * 说说自己的功课表示的是什么主题,用了哪些色相? * 说说谁的功课色彩的色相最丰厚,视觉打击力最强? 六、总结 * 经过这节课的进修,咱们...
小学语文近义词感触近义词
flash 公益广告 看了非常有感触。。。
《苦难辉煌》读书感触.docx
色彩要素在网页设计中占据着重要的地位,其重要的原因就在于由色彩要素构成的网页布局可以给予用户视觉上的冲击,色彩要素在网页布局构成中的应用,可以适当的调节用户的视觉感触,增添用户的使用感觉。 构成要素在...
最近,在运维圈里看到触控科技的萧总提出的一个概念“运维2.0”,学习之后,感触颇多,和几年前腾讯游戏的应用运维团队发起的“运维转型”战略项目神似,那个项目在数年间几乎重塑了“应用运维”在腾讯游戏的定义,...
"计算机学习心得很有感触"这个标题,意味着我们将要探讨的是一些深入且具有启发性的学习体验和见解。描述中的重复强调,进一步突显了计算机学习对于个人成长的重要影响。 在计算机科学的学习中,我们首先要了解的是...