责任链模式(Java实现)
责任链模式能够让事件处理器的逻辑与触发该事件的发送者(sender)不要绑定得过于紧密。
程序在运行过程中,会收到由某段代码所触发的事件。而相互之间形成链条的这一系列事件处理器(event handler,简称 handler,又名事件处理程序)则会依次应对该事件。每个事件处理器都可以处理这个请求,也可以决定不对该请求做出回应,并将其传给链条中的下一个事件处理器。
在实现这个模式时,可以用命令对象(command object)来表示这些事件处理器所要处理的事件。这样的话,某些事件处理器还能充当事件调度器(event dispatcher),将命令朝着不同的方向发送,从而在程序中形成一棵负责处理该命令的责任树(responsibility tree)。
责任链模式让我们能够打造一套链式的处理结构,以便在调用链条中的下一个事件处理器之前或之后执行某个特定的动作。
在 JDK 里还有一个地方也出现了责任链模式,这就是 DirectoryStream 接口,它位于 java.base 模块的 java.nio.file 包里。
DirectoryStream 接口让我们能够迭代某个目录体系,它里面还有个嵌套接口叫作 DirectoryStream.Filter,用来把不符合我们要求的目录项过滤掉。这个接口定义了 accept() 方法:
我们可以把多个 Filter 串成链条,如果前面的 Filter 无法决定是应该接受还是应该过滤,则将其交给下一个 Filter 决定。
【实例】 DriverSystem 所触发的 powerOn 事件会依次播发给责任链中的其他系统。
我们定义抽象的 VehicleSystem 类,以描述这些系统均应支持的一套功能,每个具体的系统都必须实现这些功能。另外,这个抽象类还规定了每个系统应该如何跟链条中的下一个系统相连。
【实例 2】 Java 的密封类机制让这个模式更加稳固且更易管控。

图 1 用 UML 类图来演示能够参与处理 powerOn 事件的各种 VehicleSystem 系统
有了这个模式,用户就可以动态地决定某事件应由哪些事件处理器来处理了。因此,在实现安全框架或与之类似的框架时,很值得考虑该模式。
程序在运行过程中,会收到由某段代码所触发的事件。而相互之间形成链条的这一系列事件处理器(event handler,简称 handler,又名事件处理程序)则会依次应对该事件。每个事件处理器都可以处理这个请求,也可以决定不对该请求做出回应,并将其传给链条中的下一个事件处理器。
在实现这个模式时,可以用命令对象(command object)来表示这些事件处理器所要处理的事件。这样的话,某些事件处理器还能充当事件调度器(event dispatcher),将命令朝着不同的方向发送,从而在程序中形成一棵负责处理该命令的责任树(responsibility tree)。
责任链模式让我们能够打造一套链式的处理结构,以便在调用链条中的下一个事件处理器之前或之后执行某个特定的动作。
责任链模式在JDK中的运用
在 java.logging 模块里有个名为 java.util.logging 的包,这个包中含有 Logger 类,用来记录应用程序中的各组件所发出的消息。这些 Logger 能够形成链条,使得某个日志信息可以沿着链条往下传递,一直传递到应该处理此信息的那个 Logger 实例那里。在 JDK 里还有一个地方也出现了责任链模式,这就是 DirectoryStream 接口,它位于 java.base 模块的 java.nio.file 包里。
DirectoryStream 接口让我们能够迭代某个目录体系,它里面还有个嵌套接口叫作 DirectoryStream.Filter,用来把不符合我们要求的目录项过滤掉。这个接口定义了 accept() 方法:
- 若该方法返回 true,则意味着目录中的这个项目应该接受;
- 若返回 false,则意味着应该过滤掉。
我们可以把多个 Filter 串成链条,如果前面的 Filter 无法决定是应该接受还是应该过滤,则将其交给下一个 Filter 决定。
责任链模式范例
我们举一个例子,看看怎样通过责任链模式让车辆中的各个系统依次回应由开头的 DriverSystem 所触发的事件。【实例】 DriverSystem 所触发的 powerOn 事件会依次播发给责任链中的其他系统。
System.out.println("Pattern Chain of Responsibility, vehicle system initialisation"); var engineSystem = new EngineSystem(); var driverSystem = new DriverSystem(); var transmissionSystem = new TransmissionSystem(); driverSystem.setNext(transmissionSystem); transmissionSystem.setNext(engineSystem); driverSystem.powerOn();这个程序输出结果如下:
Pattern Chain of Responsibility, vehicle system initialisation
DriverSystem: activated
TransmissionSystem: activated
EngineSystem, activated
我们定义抽象的 VehicleSystem 类,以描述这些系统均应支持的一套功能,每个具体的系统都必须实现这些功能。另外,这个抽象类还规定了每个系统应该如何跟链条中的下一个系统相连。
【实例 2】 Java 的密封类机制让这个模式更加稳固且更易管控。
sealed abstract class VehicleSystem permits DriverSystem, EngineSystem, TransmissionSystem { protected VehicleSystem nextSystem; protected boolean active; void setNext(VehicleSystem system) { this.nextSystem = system; } void powerOn() { if (!this.active) { activate(); } if (nextSystem != null) { nextSystem.powerOn(); } } }我们实现的这个范例给用户提供了一个框架,让用户可以通过该框架了解程序里有哪些系统能够串成责任链,并且知道如何让这些系统前后相连(参见下图)。

图 1 用 UML 类图来演示能够参与处理 powerOn 事件的各种 VehicleSystem 系统
总结
责任链模式让用户能够创建多个事件处理器对象,以处理程序里某个有可能影响其行为的事件。这些事件处理器对象能够适当地封装,而且彼此的逻辑互不干扰,这也符合 SOLID 设计原则。有了这个模式,用户就可以动态地决定某事件应由哪些事件处理器来处理了。因此,在实现安全框架或与之类似的框架时,很值得考虑该模式。