V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
speedcell4
V2EX  ›  Java

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

  •  
  •   speedcell4 · 2016-03-19 15:21:32 +08:00 · 2267 次点击
    这是一个创建于 2974 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    4 条回复    2016-03-19 16:47:53 +08:00
    hst001
        1
    hst001  
       2016-03-19 15:35:46 +08:00 via Android
    责任链跟继承有什么关系?
    broadliyn
        2
    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
        3
    shangjiyu  
       2016-03-19 16:31:38 +08:00
    要对修改关闭 对扩展开发
    SoloCompany
        4
    SoloCompany  
       2016-03-19 16:47:53 +08:00
    少用继承,多用复合,继承是高耦合低类聚,并且不可插拔,选择之前多自问一下,弄清楚什么是 is a 关系什么是 with a 关系应该没什么困难的吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1059 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 19:23 · PVG 03:23 · LAX 12:23 · JFK 15:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.