责任链模式( Chain of Responsibility)为什么不用继承关系实现?

2016-03-19 15:21:32 +08:00
 speedcell4

子类 if-else 判断一下是否 handle 这个 event ,不 handle 就 call 父类的 handle ,这样实现责任链不是比那种手动做链表的更方便么?为什么讲设计模式的书里都没有用继承关系来做这步呢?

2357 次点击
所在节点    Java
4 条回复
hst001
2016-03-19 15:35:46 +08:00
责任链跟继承有什么关系?
broadliyn
2016-03-19 15:52:04 +08:00
首先你要明白什么是责任链模式,通俗的说就是,如果当前这个请求是需要由我负责的,那么我就处理这个请求,否则我就把请求递交给下一个负责任。

这里需要明确的是,当前所处的“我”这个负责人并不需要关心上一个负责人或者下一个负责人,也就是说“我”这个负责人并不能直接与相邻的负责人进行交互。好比快递员, a 快递给 b 一件货物, a 与 b 并不是直接交接,而是 a 把快递送到物流公司,再由物流公司送到 b'手上, b'收到货物发现不是自己的,然后 b'再把快递送回物流公司,物流公司最终送到 b 手上。

而如果用继承的方式,有两个缺陷:
1.责任人之间有交互了,增加了耦合性,不符合责任链可插拔的特性。
2.责任链传递方向只能从子类到父类(通过 super.xxxChain() 方式)。而往往常见的责任链模式一般都是从头到尾,然后再从尾到头。比如 servlet 里的 filter , http request 通过 N 层的 filter 到达 servlet 后, servlet 返回的 response 也需要通过这 N 层的 filter 再返回给客户端。 netty 的 channel 、 spring 拦截器也都是这个原理。

还有一个理由也能算是缺陷, java 设计模式里一般比较忌讳继承。特别的,如果你有三个 Filter 分别是 AFilter , BFilter , CFilter , C 继承自 B , B 继承自 A ,假设中间你需要把 BFilter 给去掉,那么 CFilter 的代码就会报错,此时你就需要手动修改 CFilter extends AFilter ,因为去掉一个责任人而导致其他部分的代码也跟着需要修改,明显是不符合设计模式的初衷的。
shangjiyu
2016-03-19 16:31:38 +08:00
要对修改关闭 对扩展开发
SoloCompany
2016-03-19 16:47:53 +08:00
少用继承,多用复合,继承是高耦合低类聚,并且不可插拔,选择之前多自问一下,弄清楚什么是 is a 关系什么是 with a 关系应该没什么困难的吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/264723

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX