在 Android 开发中,责任链模式(Chain of Responsibility Pattern)是一种常用的行为型设计模式,其核心思想是将多个请求处理者通过“链”的形式连接起来,使请求沿着链传递,直到被某个处理者处理为止。这种模式能有效降低请求发送者与处理者之间的耦合,让每个处理者只关注自己能处理的请求,同时支持动态扩展处理者。
一、责任链模式的核心角色
责任链模式通常包含以下 3 个核心角色:
-
抽象处理者(Handler)
定义处理请求的接口,包含一个指向“下一个处理者”的引用(即链的连接点),以及处理请求的抽象方法。 -
具体处理者(ConcreteHandler)
实现抽象处理者的接口,负责处理特定类型的请求。如果自身能处理请求,则直接处理;否则将请求传递给“下一个处理者”。 -
请求(Request)
包含需要被处理的信息(如请求类型、参数等),是传递在链中的数据载体。
二、责任链模式的工作流程
- 多个具体处理者通过“下一个处理者”的引用形成一条链;
- 当一个请求进入链中时,从链的第一个处理者开始尝试处理;
- 若当前处理者能处理请求,则直接处理并终止传递;
- 若不能处理,则通过引用将请求传递给下一个处理者;
- 以此类推,直到请求被处理或到达链的末尾(未被处理)。
三、责任链模式的优缺点
优点:
- 降低耦合度:请求发送者无需知道具体由哪个处理者处理,只需将请求投入链中即可。
- 灵活性高:可动态增减处理者或调整链的顺序,符合“开闭原则”。
- 分工明确:每个处理者只处理自己职责范围内的请求,逻辑清晰。
缺点:
- 请求可能未被处理:若链中所有处理者都无法处理请求,可能导致请求“丢失”(需提前设计兜底方案)。
- 性能影响:链过长时,请求传递会增加耗时,影响效率。
四、Android 中责任链模式的典型应用
责任链模式在 Android 框架和主流库中被广泛使用,以下是几个典型场景:
1. OkHttp 的拦截器链(Interceptor Chain)
OkHttp 的拦截器是责任链模式的经典实现,用于处理网络请求的各个环节(如日志、缓存、重定向等)。
- 抽象处理者:
Interceptor
接口,其intercept(Chain chain)
方法定义处理逻辑。 - 链的管理:
RealInterceptorChain
实现Chain
接口,通过proceed(request)
方法将请求传递给下一个拦截器。 - 具体处理者:如
RetryAndFollowUpInterceptor
(重试/重定向)、CacheInterceptor
(缓存处理)、CallServerInterceptor
(发送请求)等,每个拦截器负责特定逻辑,不处理则通过chain.proceed()
传递给下一个。
// 拦截器接口(抽象处理者)
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
Response proceed(Request request) throws IOException; // 传递给下一个处理者
}
}
// 具体处理者示例(日志拦截器)
public class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 处理请求(记录日志)
Log.d("OkHttp", "Request: " + request.url());
// 传递给下一个拦截器
Response response = chain.proceed(request);
// 处理响应(记录日志)
Log.d("OkHttp", "Response: " + response.code());
return response;
}
}
2. View 的事件分发机制
Android 中 View 的触摸事件(如 onTouchEvent
)传递是责任链模式的体现,事件从顶层 View(如 Activity)向下传递,直到被某个 View 消费。
- 链的结构:View 树中,事件从
Activity
→ViewGroup
→View
逐层传递(或反向传递)。 - 处理逻辑:每个 View 通过
onTouchEvent(MotionEvent event)
决定是否处理事件(返回true
表示消费,事件终止;返回false
表示不处理,事件传递给父 View)。
// View 事件处理示例(简化)
public boolean onTouchEvent(MotionEvent event) {
if (canHandle(event)) { // 自身能处理(如点击事件)
handleEvent(event);
return true; // 终止传递
} else {
return false; // 传递给父 View
}
}
3. 有序广播(Ordered Broadcast)
Android 的有序广播按优先级形成责任链,每个 BroadcastReceiver
可处理或终止广播。
- 链的顺序:通过
android:priority
属性指定接收者优先级,优先级高的先接收。 - 处理逻辑:接收者通过
abortBroadcast()
终止广播,否则传递给下一个优先级低的接收者。
4. 输入事件处理(InputEventReceiver)
Android 系统的输入事件(如按键、触摸)通过 InputEventReceiver
形成链,从系统层传递到应用层,每层可处理或转发事件。
五、自定义责任链模式示例
假设需要设计一个“日志处理系统”,按日志级别(Debug < Info < Error)由不同处理者处理,若无法处理则传递给下一个。
步骤 1:定义日志请求类(Request)
// 日志请求:包含级别和内容
public class LogRequest {
public enum Level { DEBUG, INFO, ERROR }
private Level level;
private String message;
public LogRequest(Level level, String message) {
this.level = level;
this.message = message;
}
public Level getLevel() { return level; }
public String getMessage() { return message; }
}
步骤 2:定义抽象处理者(Handler)
// 抽象日志处理者
public abstract class LogHandler {
// 下一个处理者
protected LogHandler nextHandler;
public LogHandler(LogHandler nextHandler) {
this.nextHandler = nextHandler;
}
// 处理请求的抽象方法
public abstract void handle(LogRequest request);
}
步骤 3:实现具体处理者
// 处理 Debug 级日志
public class DebugLogHandler extends LogHandler {
public DebugLogHandler(LogHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(LogRequest request) {
if (request.getLevel() == LogRequest.Level.DEBUG) {
Log.d("DebugLog", request.getMessage());
} else if (nextHandler != null) {
// 无法处理,传递给下一个
nextHandler.handle(request);
}
}
}
// 处理 Info 级日志
public class InfoLogHandler extends LogHandler {
public InfoLogHandler(LogHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(LogRequest request) {
if (request.getLevel() == LogRequest.Level.INFO) {
Log.i("InfoLog", request.getMessage());
} else if (nextHandler != null) {
nextHandler.handle(request);
}
}
}
// 处理 Error 级日志(兜底处理)
public class ErrorLogHandler extends LogHandler {
public ErrorLogHandler(LogHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(LogRequest request) {
if (request.getLevel() == LogRequest.Level.ERROR) {
Log.e("ErrorLog", request.getMessage());
} else if (nextHandler != null) {
nextHandler.handle(request);
} else {
// 所有处理者都无法处理,兜底提示
Log.w("LogHandler", "未处理的日志:" + request.getMessage());
}
}
}
步骤 4:构建责任链并使用
public class Main {
public static void main(String[] args) {
// 构建链:Debug → Info → Error(Error 为最后一个处理者)
LogHandler errorHandler = new ErrorLogHandler(null);
LogHandler infoHandler = new InfoLogHandler(errorHandler);
LogHandler debugHandler = new DebugLogHandler(infoHandler);
// 发送不同级别的日志请求
debugHandler.handle(new LogRequest(LogRequest.Level.DEBUG, "调试信息")); // DebugLog 处理
debugHandler.handle(new LogRequest(LogRequest.Level.INFO, "普通信息")); // InfoLog 处理
debugHandler.handle(new LogRequest(LogRequest.Level.ERROR, "错误信息")); // ErrorLog 处理
}
}
输出结果:
D/DebugLog: 调试信息
I/InfoLog: 普通信息
E/ErrorLog: 错误信息
六、总结
责任链模式通过“链”的形式将处理者解耦,适用于“多个对象可能处理同一请求,且处理者不确定”的场景。在 Android 开发中,理解 OkHttp 拦截器、View 事件分发等框架级应用,能帮助我们更灵活地设计自己的业务逻辑(如权限校验链、数据过滤链等)。使用时需注意控制链的长度,避免性能问题,并确保请求有兜底处理方案。