本章主要讨论行为型设计模式,即为了某些应用场景或者实现某个目的,我们的类有一些比较特殊的行为。该类设计模式也是比较难以理解的设计模式类型之一。

第一条 责任链模式(Chain of responsibility)

适用场景

  1. 责任链模式实际上是一种用来解耦请求方和处理方的模式
  2. 当请求方发出请求时,可能不止有一个对象要去处理请求,并且事先并不知道谁要处理这个请求,请求的处理者是动态决定的。
  3. 当请求方发出请求时,并不关心请求究竟被谁执行了,即请求方与处理方是解耦的
  4. 可以处理请求的一组对象是被动态地指定的

如何做

如下图: {% asset_img chain_1.png %} 在图中,我们有一个请求方OrcKing,即兽王。与其说是请求方,不如说是发号施令者。 最左边我们可以看到,RequestType定义我们的兽王有三种命令可以发布,保护城堡(DEFEND_CASTLE)、审问犯人(TORTURE_PRISONER)、收税(COLLECT_TAX)。 然后我们的兽王,有个buildChain()方法,该方法会在构造函数中调用,目的是创建一个RequestHandler然后保存在内部域中。 我们有三个命令的处理方,即兽王的三个手下,兽族战士(OrcSoldier)、兽族指挥官(OrcCommander)、兽族官员(OrcOfficer)。它们都继承自抽象类RequestHandler。 每个处理方的构造函数,都会传入另一个处理方,这边是责任链构造的关键点。 我们兽王在使用buildChain()方法的时候,责任链的构造代码是下面这样的:

private void buildChain() {
    chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null)));
  }

可以看到,最终兽王内部的域拿到的其实是兽族指挥官的引用,因此,当兽王下令的时候,它使用makeRequest(Request)方法,会优先将命令传达给兽族指挥官。 兽族指挥官此时会检查命令的类型,他只能处理保护城堡这种命令,如果它发现自己处理不了,就将命令丢给构造函数传进来的那个人,也就是我们的兽族官员。 兽族官员也会检查命令的类型,他只能处理审问犯人的命令,如果发现不是审问犯人的命令,他就再将命令继续往下传,传给兽族战士。以此类推,直到责任链的末尾。

好处

  1. 请求和处理方解耦
  2. 稍加改造,在处理之后,处理方仍然将请求传递下去,请求就可以被多个处理方处理,类似广播一样,所有的处理方都能感知到请求并选择是否处理

坏处

  1. 如果责任链太长,效率会降低,如果一个请求只需要给某一个处理方处理,而这个处理方总是在责任链的最后,程序效率会变差。
  2. 责任链对先后顺序敏感,如果有些处理对顺序有要求,则责任链很容易不满足需求。比如,ABCD四个处理类,要求A必须在C之前执行,B必须在A之前执行,C又必须在B之前执行
  3. 责任链上所有的类都被耦合在了一起,其中一个类出错,有可能影响后面所有类的行为。
  4. 对于需要有个回答的请求,责任链可能比较吃力,也许结合回调模式能够做到