意图
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
用来解耦,客户只要把消息发到责任链上,无需关注请求细节和传递过程
实例
场景:我们在开发应用系统的过程中,经常会遇到记录日志的需求。日志分为三种类型,分别是INFO(消息)、DEBUG(调试) 、ERROR(报错),当需要记录日志的时候,通过判断看看日志属于哪种类型, 然后对应的日志处理类再去处理相应的日志信息。
//抽象的日志记录器类
public abstract class AbstractLogger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;
protected int level;
/**
* 责任链中的下一个元素
*/
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLogger nextLogger){
this.nextLogger = nextLogger;
}
public void logMessage(int level, String message){
if(this.level <= level){
write(message);
}
if(nextLogger !=null){
nextLogger.logMessage(level, message);
}
}
abstract protected void write(String message);
}
//创建扩展了该记录器类的实体类
class InfoLogger extends AbstractLogger {
public InfoLogger(int level){
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Info Logger:" + message);
}
}
class DeBugLogger extends AbstractLogger {
public DeBugLogger(int level){
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("DeBug Logger:" + message);
}
}
class ErrorLogger extends AbstractLogger {
public ErrorLogger(int level){
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Error Logger:" + message);
}
}
public class Test {
private static AbstractLogger getChainOfLoggers(){
AbstractLogger infoLogger = new InfoLogger(AbstractLogger.INFO);
AbstractLogger deBugLogger = new DeBugLogger(AbstractLogger.DEBUG);
AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
infoLogger.setNextLogger(deBugLogger);
deBugLogger.setNextLogger(errorLogger);
return infoLogger;
}
public static void main(String[] args) {
AbstractLogger loggerChain = getChainOfLoggers();
loggerChain.logMessage(AbstractLogger.INFO, "这是普通日志信息");
loggerChain.logMessage(AbstractLogger.DEBUG,"这是调试日志信息");
loggerChain.logMessage(AbstractLogger.ERROR,"这是错误日志信息");
}
}
运行结果
Task :lib:test.main()
Info Logger:这是普通日志信息
Info Logger:这是调试日志信息
Info Logger:这是调试日志信息
Info Logger:这是错误日志信息
Info Logger:这是错误日志信息
Info Logger:这是错误日志信息
责任链就是想链条一样,一个个传递,也可以在中间增加或减少。
在android中,事件分发机制,父View接到事件,传递给子View。在第三方库okhttp中的拦截器。
//okhttp拦截器源码
Response getResponseWithInterceptorChain() throws IOException {
//以下通过将所有的连接器加入到集合中
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors()); //此处为添加客户端自定义的拦截器
//其后添加五个内置拦截器
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
//如果没有使用代理连接,添加网络拦截器,也是客户端自定义拦截器
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
//创建拦截器链对象,主要用于控制拦截器的顺序执行和各拦截器的加工结果
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
优点:
- 降低耦合度。它将请求的发送者和接收者解耦。
- 简化了对象。使得对象不需要知道链的结构。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 增加新的请求处理类很方便。
- 实现了责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
- 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 不好调试。