什么是责任链模式?
责任链模式是一种对象行为型模式。
责任链模式避免请求发送者和接受者耦合在一起,使多个对象都有可能接受请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
我们经常使用的的HttpClient,就是一种责任链处理模型,请求一步一步的处理,直到处理完成,这个链式结构可以是直线型,也可以是环形或者是树形结构。
核心结构
- Handler。抽象处理者,定义处理请求的接口,通常设计为抽象类,并声明抽象请求处理方法,然子类各自进行不同的处理实现。在抽象请求处理方法中还需要定义对下一节点的引用,通过引用将这个请求处理模型连接成链。
- ConcreteHandler。具体处理者,实现了抽象处理者,完成具体的请求处理,并将引用转移至下一个节点。
类图展示
代码分析
在处理消息时,我们通常需要经过消息组装、通道选择、系统选择等步骤,在常规的开发模式中,我们可能将所有逻辑写到一个方法中,今天我们就用责任链模式对这一流程进行改装。
首先我们定义一个抽象处理者,它主要声明了处理方法:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/13 0013.
* 责任链模式——抽象处理者
*/
public abstract class Processor {
protected Processor processor;
public void setProcessor(Processor processor) {
this.processor = processor;
}
public abstract void processRequest(Request request);
}
接着,我们根据三种不同的业务情景,实现三种不同的处理者:
消息组装:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/13 0013.
* 责任链模式——具体处理者
*/
public class MessageProcessor extends Processor {
@Override
public void processRequest(Request request) {
if((StringUtils.isNotBlank(request.getChannel())) && (StringUtils.isBlank(request.getMessage()))) {
request.setMessage("message loading...");
System.out.println("2017年春运大幕正式开启");
}
this.processor.processRequest(request);
}
}
通道选择:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/13 0013.
* 责任链模式——具体处理者
*/
public class ChannelProcessor extends Processor {
@Override
public void processRequest(Request request) {
if ((StringUtils.isBlank(request.getMessage())) && (StringUtils.isBlank(request.getSystem()))) {
request.setChannel("the third party");
System.out.println("channel selecting...");
}
this.processor.processRequest(request);
}
}
系统选择:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/13 0013.
*/
public class SystemProcessor extends Processor {
@Override
public void processRequest(Request request) {
if((StringUtils.isNotBlank(request.getChannel())) && (StringUtils.isNotBlank(request.getMessage()))){
request.setSystem("all");
System.out.println("system choosing...");
System.out.println("sending");
System.out.println("success, over");
}
}
}
接着我们定义一个请求类:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/13 0013.
* 责任链模式——请求类
*/
public class Request {
private String message;
private String channel;
private String system;
public Request(String message, String channel, String system) {
this.message = message;
this.channel = channel;
this.system = system;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getChannel() {
return channel;
}
public void setChannel(String channel) {
this.channel = channel;
}
public String getSystem() {
return system;
}
public void setSystem(String system) {
this.system = system;
}
public String toString() {
return "channel: " + channel + ", message: " + message + "system: " + system;
}
}
完活,上测试代码:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/13 0013.
* 责任链模式测试
*/
public class ChainTest {
public static void main(String[] args) {
chainTest();
}
private static void chainTest() {
try {
Processor channel, message, system;
channel = new ChannelProcessor();
message = new MessageProcessor();
system = new SystemProcessor();
// 创建责任链
channel.setProcessor(message);
message.setProcessor(system);
Request requestOne = new Request("", "", "");
channel.processRequest(requestOne);
} catch (Exception e) {
e.printStackTrace();
}
}
}
模式总结
优点
- 降低了系统的耦合度,链中传递的对象无需知道链的结构,也不需要知道哪一个对象处理请求,仅知道请求会被处理,相当于沿着跑道跑,终究会来到终点。
- 处理者仅需维护一个向后传递对象的引用,不需要维持对所有处理者的引用,简化了对象之间的关联关系。
- 为系统提供了更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来新增或修改一个请求的职责。
- 在新增具体请求处理者时无需改动其他代码,外部调用重新建链即可,此点符合开闭原则。
缺点
- 责任链较长可能会影响系统的性能。
- 建链不当可能会引起循环调用,进入死循环,导致内存溢出。
- 对象可能在责任链中没有具体处理者,造成性能浪费,并且可能由于没有正确建链导致对象没有被处理。
适用场景
- 一个对象需要多个处理环节,在运行时才会确定处理顺序,客户端只需要建链即可,无需关注处理细节。
- 外部调用需要动态处理请求,或是需要经常变更对象的处理顺序。
- 在不明确指定接受者的情况下,向多个对象中的一个提交请求。