首    页 建模架构 设计模式 培训咨询 jdon框架 论坛

AOP vs Decorator

板桥里人 http://www.jdon.com 2006/1/2(转载请保留)

  更确切地说,我们在比较AOP的拦截器和Decorator模式,它们非常相似,一些AOP框架本身就是使用Decorator模式来实现拦截器功能的。

  过滤器是架构设计模式中比较常用的一种,几乎每个灵活动态系统都需要过滤器,特别是当我们的数据以内存状态出现时,过滤器无疑成为领域层的一个核心业务逻辑,当然如果你还是使用面向数据库的编程模式,过滤器功能就被你用SQL语句的where语法给替代了,那么以下你可能不必再看,请浏览这篇文章:状态对象:数据库的替代者

  当我们在一个AOP框架下编程,经常会问自己,到底过滤器这个功能是应该做成拦截器还是
Decorator,当我在Jdon Framework下重写JiveJdon时就不只一次的问我自己。

  其实这是一个分析模式中的过滤器实现问题,也是一个现实设计的问题:在Servlet Filter和职责链以及装饰模式Decorator和AOP几个方面如何选择?

  选择标准无外乎软件的两个终极目标:简单和高质量;高质量是反映在细粒度方面,简单则是在进行设计实现时比较容易方便。

  在粒度粗细方面,又有一个衡量指标:功能覆盖范围,也是一个scope,例如:如果功能需求要为某个类的方法实现实现过滤,但是,你使用一个Servlet Filter这样过滤器实现,虽然
它也能够实现我们的目标,但是它对所有的Servlet请求都进行过滤,这无疑范了杀鸡取卵的错误,造成系统性能上的损失。

  以一个具体案例为例子:
  我们在论坛显示时,希望动态过滤掉不应该出现的字眼,也就是在帖子显示之前,加载一个过滤器,对内容进行替换。

  这里的Model是ForumMessage,而对应的Service则是ForumMessageService; ForumMessageService的getMessage可以获得帖子内容,这里我们在getMessage之前加一个过滤器;那么这里应该如何选择呢?

  因为我在Jdon Framework这样的Ioc/AOP框架下实现,所以想到的是AOP,我们定义一个拦截器,拦截的对象是ForumMessageService的getMessage方法,进行配置文件配置即可。似乎很简单很酷,可是真的很美丽吗?

  这里,我们从原理上这几个过滤器实现进行解析一下:
  我这里举个例子,你想向处于同一个城市对方送达一个信件,这时有两种选择:
  1.委托高效的TNT UPS等快递公司
  2.亲自跑一趟。

  这两种哪个效率最高?无疑是亲自跑一趟,可能半个小时或一个小时解决问题,但是你一旦委托第三方,我想,无论快递公司如何高效,肯定没有你自己解决快速。所以,当你能够自己处理把握时,亲自动手无疑最快的。

  编码时也类似这样,如果你能在编码时,能够确定拦截那个类哪个方法,有什么比你直接写代码还能执行更快的呢?

  AOP的拦截器实现原理也是这样,当然,正是有这种考虑,所以所有AOP框架内,只有 AspectJ性能是最好的,因为它在你编译代码时就将你的拦截意图实现了,这属于静态织入 weaving,这就类似你自己写代码实现,但是与你自己写代码不同的是,你自己不但要写拦截器,而且还要自己手工将拦截器语句插入被拦截的那段代码,现在,使用AspectJ你就不用做后者了,这也是整合了AspectJ的Spring 2.0给我们带来的效能。所以,为了在编译代码时做手脚,就不能使用SUN的JDK原来的javac了,必须用他们自己特定的javac了。有得必有失吧。

  理解了AOP拦截器拦截的原理,你可能感慨:原来所有的动态AOP(不改换编译器的AOP框架)拦截效能没有Decorator直接指定要快啊。所以,如果你在编码设计阶段,可以知道你所要拦截的方法,那么,无疑直接使用Decorator模式组成过滤器是一种好方式。

  这也是我先期不怎么看好使用动态AOP实现的Spring 1.X版本,也不太热衷于同样使用
动态AOP实现、虽符合EJB 3.0规范的JBoss 4.0了。可是,为什么总是有人迫不及待地告别EJB 2.x,夸张Spring,然后又狂炫EJB 3.0。在接纳他们之前,先把盒子打开看看验货一下,做一个普通的消费者应有的理性。

  当然,不是说动态AOP没有用武之地,它类似SOA的集成作用,可以在不用修改原来代码结构上强行加入过滤器。而且AOP不只是拦截器,还有introduction,这一神奇功能可以突破Java单继承法则,显得象儿童世界里面的神奇魔法一样。

  从某个方面来说,动态AOP和职责链非常类似,职责链类似击鼓传花,更像典型的打太极拳,推来推去,这也是政府效率不高的主要原因,同样,用在软件系统里,性能最差。想象一下,当这朵花传到真正主人面前时,而这个主人是传花环节中最后一个,这种效率和直接抛绣球一样,直接将花抛给真正主人相比,无疑最耗时间的,所以击鼓传花游戏就是玩的这个耗时间,在鼓声中,消耗时间,煎熬折磨你的心思,它玩的不是要把花如何快速准确地送给某人,它的目的性不确切。

  我们的软件系统不能这么玩吧?

  总结如下:过滤器实现方式在不保证功能前提下,从性能角度考虑有如下先后顺序:Decorator或Proxy模式;AOP拦截器。

  考虑使用AOP拦截器时,最好选择那些受众面积比较广的功能,例如一些基础通用功能:权限检查;事务机制;Pool等,这些功能不是针对某个具体类或方法(方法权限除外),而是一系列类,这样使用动态AOP拦截器,就是有些性能损耗也是值得的,而且是必要的,使用其他方法也会引起这样的损耗。

  如果过滤器是业务逻辑的一部分,而且在设计时,我们可以确定这些过滤器,这样我们使用Decorator模式或Proxy模式进行特定指定的拦截,当然,因为每个类/接口都需要一个附加的Decorator/Proxy,如果某个过滤功能是很多类都需要的,会形成很多Decorator/Proxy附加类,当点形成面时,这时AOP切面概念就应该浮现在你脑海,这时升级使用AOP拦截器就更好。Decorator/Proxy在点上针对性相当强,特别在这个点上有一系列过滤器需要实现时。

  职责链和Decorator/AOP拦截器是有些区别的,在一个动态运行系统中,有两个概念:由客户端触发的请求对象,该请求对象需要穿透一系列过滤器(防火墙),最终可能达到持久层数据库。Decorator/AOP拦截器是对过滤器管理的一种模式,也就是说:怎么设计过滤器类;过滤器类关系是怎样;而职责链不是对类关系管理定义,而是为了处理某个请求对象而实现的。他们区别在于目标对象不一样,所以职责链是一种很具体的行为。

  在这个层面上,Command模式和其是相竞争的,Command模式类似直接抛绣球,知道目的,能够最有效率,但是前提在设计编码阶段你必须知道你的目的地;Command模式和职责链的区别与Decorator和AOP拦截器的区别是类似的。

相关资料:

国人最早开源IOC/AOP框架JdonFramework

JiveJdon3全新架构文档和源码

Decorator模式、BUG和AOP

AOP是什么?

AOP详解和AspectJ

GOF 23种设计模式

Decorator模式

你还在用if else吗?

发布讨论

更多AOP专题

更多Decorator模式

更多关于AOP讨论


更多标签...



Jdon框架演示

JiveJdon
源码下载

VIP收费区

历史热点讨论排行榜




google yahoo 新浪ViVi 365Key网摘 天极网摘 CSDN网摘 添加到百度搜藏 POCO网摘





手机 add to google add to yahoo
联系我们 | 关于我们 | 广告联系 | 网站地图 | 设为首页

沪ICP证08026060 如有意见请与我们联系 Powered by JdonFramework
_×
您有新消息