一、介绍
责任链模式属于行为型模式,通常会实现成链表型结构,链表的每个节点是具体行为的处理者,负责业务的整体处理(纯责任链)或者部分处理(不纯责任链)职责。责任链模式解耦了不同的处理方式处理行为,方便于新的职责行为的加入(对扩展开放)。换句话说就是,每个负责处理业务的对象,链接成一条链,请求在这条链中进行传递,如当前节点可以处理该请求,就交给该节点进行处理,如果当前节点不符合处理的条件,就将处理的任务传递给链条中的下一节点。

二、实现举例
我们通过实现一个消息处理的责任链来深入学习责任链模式。具体场景是,项目中需要实现消息推送的功能,消息的推送渠道有微信,短信等,根据客户绑定的通知类型不同,我们需要组装不同的消息,调用不同的SDK给客户推送通知,我们来看下一般实现怎么处理:
// 请求对象
public class Request {
private Long customerId; // 客户ID
private String channel; // 绑定通知渠道(微信、短信)
private String message; // 具体消息。。。
...
}
// 消息处理类
public class MessageHandler {
// 处理消息的方法
public void handle(Request request){
if(request.channel == '微信'){
// 发微信
} else if(request.channel == '短信'){
// 发短信
} else {
// 不做操作
}
}
}
最简单的方式就是通过if-else判断,根据不同的消息类型,做不同的消息处理,但是如果之后需要扩展,比如APP接入了第三方消息推送,那么就需要修改上面这段代码,新增一段else-if的判断,然后再写第三方推送的逻辑。这样做有什么问题呢?最明显的就是违反了面向对象的开闭原则(对扩展开放,对修改关闭)上面接入第三方推送属于一个需要扩展的场景,而通过这种方式实现,对扩展是不友好的,因为每次扩展都需要修改这部分代码从而引入风险。
我们来看怎样通过责任链模式进行优化:
// 抽象处理类,每一个具体处理节点,继承自该类
public abstract class MessageHandler {
// 当前节点持有下一处理节点的引用
protected MessageHandler successor;
// 构造链的下一处理节点
public MessageHandler(MessageHandler successor) {
this.successor = successor;
}
// 子类需要实现该方法做具体处理
protected abstract void handle(Request request);
}
// 发微信的消息处理类
public class WeChatMessageHandler extends MessageHandler {
public WeChatMessageHandler(MessageHandler successor) {
super(successor);
}
@Override
protected void handle(Request request) {
if (request.channel == '微信') {
// 发微信操作
return;
}
if (successor != null) { // 如果不属于发微信类型,职责向链表下一环传递
successor.handle(request);
}
}
}
// 发短信的消息处理类
public class SMSMessageHandler extends MessageHandler {
public SMSMessageHandler(MessageHandler successor) {
super(successor);
}
@Override
protected void handle(Request request) {
if (request.channel == '短信') {
// 发短信操作
return;
}
if (successor != null) { // 如果不属于发短信类型,职责向链表下一环传递
successor.handle(request);
}
}
}
// 客户端发送消息操作
public class Client {
public static void main(String[] args) {
MessageHandler wechatMsgHandler = new WeChatMessageHandler(null);
MessageHandler smsMsgHandler = new SMSMessageHandler(wechatMsgHandler);
Request req = new Request("微信");
smsMsgHandler.handle(req);
}
}
如果需要扩展,我们只需要新建一个消息处理类,明确该类所能处理的消息类型,然后将该类加入到整个责任链中。
// 第三方消息平台的消息处理类
public class OtherMessageHandler extends MessageHandler {
public OtherMessageHandler(MessageHandler successor) {
super(successor);
}
@Override
protected void handle(Request request) {
if (request.channel == '第三方消息平台') {
// 第三方消息平台推送操作
return;
}
if (successor != null) {
successor.handle(request);
}
}
}
在客户端调用操作中我们将新扩展的处理类加入到整个责任链中:
// 客户端发送消息操作
public class Client {
public static void main(String[] args) {
MessageHandler otherMsgHandler = new OtherMessageHandler(null);// 新加入的处理类
MessageHandler wechatMsgHandler = new WeChatMessageHandler(otherMsgHandler);
MessageHandler smsMsgHandler = new SMSMessageHandler(wechatMsgHandler);
Request req = new Request("第三方消息平台");
smsMsgHandler.handle(req);
}
}
这样,如果再有新消息推送平台接入,我们只需要新增具体的推送类,并且修改调用处的代码将新实现的处理类加入链中就可以了,不会影响或者去修改之前已有的推送相关代码。
三、其他应用
JDK中很多实现也运用了责任链模式,感兴趣的话,可以研究一下具体实现。