标签:
最近在设计框架时,需要设计一类扩展点,发现不能简单地继承或使用事件来给使用者提供 API。最终使用拦截器模式解决了 API 的设计。
扩展点使用场景
该扩展点的使用场景如下:
扩展点设计方案选型
在框架设计时,扩展点设计主要通过几种类型的 API 来提供:虚方法、事件、接口。(关于扩展点的设计,详细的内容,参见:《Framework Design Guidelines 2nd Edition》第六章,扩展性设计。)而最常用、最方便使用者使用的扩展点则是前两个:虚方法和事件。
前两种扩展点设计方案的主要区别在于:
可以看出,如果是想设计一类提供给继承体系外类型进行扩展的扩展点, 虚方法、事件两类 API 都不合适。那我们只能在第三种方式上想办法:接口。接口的设计则非常灵活,而其实我上面描述的场景会经常遇到,所以应该提取出一类设计模式。经过一番思考,我发现其实拦截器模式比较适合该场景。拦截器模式本身注重对消息、方法的拦截处理,是一种继承体系外的扩展方法,并被大量用于 AOP 的实现。在这里采用该模式,我们更加关注其在真正核心方法调用前后的扩展机制、以及核心方法的阻断机制,以及最终扩展 API 提供的形式。
实现
该模式放到 Rafy 中实现提交时的扩展点后,类图如下:
扩展点使用方法也较简单,使用者继承拦截器,编写相应的扩展逻辑即可:
有一个细节需要注意:上图中能看到,方法的第一个参数也是一个自定义的参数类型 SubmitArgs。但是由于拦截器是一种链式调用,所以这个类型可以采用值类型;在此方法被大量调用时,相对于事件的扩展机制,没有大量的冗余对象。
在启动时,加入以下代码就可以把该拦截器添加到保存的拦截器列表中:
总结
拦截器模式实现起来比较简单,该模式的结构非常类似于 GOF 中的职责链模式,只是关注点不同。在使用它作为扩展点时,对于使用者来说也比较易用,而且性能相对于事件机制来说更好,所以可以直接作为一种常用的扩展点设计方案。
标签:
原文地址:http://www.cnblogs.com/zgynhqf/p/4998606.html