一、故事解说:公司请假流程如何层层审批
假设你在一家公司上班,请假流程如下:
-
提交申请:你向直属领导提交请假申请(比如 3 天);
-
领导审批:
- 直属领导(组长):只能批 1 天内的假,超过则转给上级;
- 部门经理:能批 3 天内的假,超过则转给总监;
- 总监:能批 7 天内的假,超过则转给 CEO;
-
最终处理:CEO 可以批任意天数的假。
责任链核心:请求(请假)在链条(各级领导)中传递,每个处理者(领导)决定是否处理或传递给下一个。
二、责任链模式核心结构(请假流程案例)
java
// 1. 抽象处理者:领导
abstract class Leader {
protected Leader nextLeader; // 下一个处理者
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}
// 处理请求的抽象方法
public abstract void handleRequest(int days);
}
// 2. 具体处理者:组长(1天内)
class TeamLeader extends Leader {
@Override
public void handleRequest(int days) {
if (days <= 1) {
System.out.println("组长批准" + days + "天假");
} else if (nextLeader != null) {
nextLeader.handleRequest(days); // 传递给下一个
} else {
System.out.println("请假天数过长,无人处理");
}
}
}
// 3. 具体处理者:部门经理(3天内)
class DepartmentManager extends Leader {
@Override
public void handleRequest(int days) {
if (days <= 3) {
System.out.println("部门经理批准" + days + "天假");
} else if (nextLeader != null) {
nextLeader.handleRequest(days);
} else {
System.out.println("请假天数过长,无人处理");
}
}
}
// 4. 具体处理者:总监(7天内)
class Director extends Leader {
@Override
public void handleRequest(int days) {
if (days <= 7) {
System.out.println("总监批准" + days + "天假");
} else if (nextLeader != null) {
nextLeader.handleRequest(days);
} else {
System.out.println("请假天数过长,无人处理");
}
}
}
// 5. 客户端:创建链条并提交请求
public class Client {
public static void main(String[] args) {
// 创建处理者
Leader teamLeader = new TeamLeader();
Leader manager = new DepartmentManager();
Leader director = new Director();
// 组装链条
teamLeader.setNextLeader(manager);
manager.setNextLeader(director);
// 提交请求
teamLeader.handleRequest(2); // 部门经理批准2天假
teamLeader.handleRequest(5); // 总监批准5天假
teamLeader.handleRequest(10); // 请假天数过长,无人处理
}
}
三、Android 常用责任链模式案例与实现
案例 1:Android 事件分发机制
java
// 1. 抽象处理者:View
public abstract class View {
private ViewParent parent; // 父容器
public void setParent(ViewParent parent) {
this.parent = parent;
}
// 事件分发方法(类似责任链的handleRequest)
public boolean dispatchTouchEvent(MotionEvent event) {
// 1. 自己先尝试处理事件
if (onTouchEvent(event)) {
return true; // 自己处理了,终止传递
}
// 2. 自己不处理,传递给父容器
if (parent != null) {
return parent.requestDisallowInterceptTouchEvent(event);
}
return false; // 无人处理
}
// 处理事件的方法(子类实现)
public boolean onTouchEvent(MotionEvent event) {
return false; // 默认不处理
}
}
// 2. 具体处理者:Button(处理点击事件)
public class Button extends View {
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
// 处理点击事件
performClick();
return true; // 处理了事件,终止传递
}
return false;
}
public void performClick() {
System.out.println("Button clicked");
}
}
// 3. 具体处理者:ViewGroup(可包含子View)
public class ViewGroup extends View {
private List<View> children = new ArrayList<>();
public void addView(View view) {
children.add(view);
view.setParent(this);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
// 1. 先尝试分发给子View
for (View child : children) {
if (child.dispatchTouchEvent(event)) {
return true; // 子View处理了,终止传递
}
}
// 2. 子View都不处理,自己处理
return super.dispatchTouchEvent(event);
}
}
// 4. 使用方式(类似Activity中设置布局)
public class MainActivity {
public void onCreate() {
// 创建布局
ViewGroup root = new ViewGroup();
Button button = new Button();
root.addView(button);
// 模拟点击事件
MotionEvent event = MotionEvent.obtain(
System.currentTimeMillis(),
System.currentTimeMillis(),
MotionEvent.ACTION_UP,
100, 100, 0);
root.dispatchTouchEvent(event); // 事件从根布局开始传递
}
}
优点:
-
解耦事件处理:View 只需关注自身是否处理事件,无需知道其他 View 的存在;
-
灵活定制:可通过重写
dispatchTouchEvent或onTouchEvent改变事件传递规则; -
符合 Android 设计:Android 系统的事件分发机制就是责任链模式的经典应用。
缺点:
- 调试困难:事件传递路径可能很长,出错时难以定位问题;
- 性能问题:如果链条过长或每个节点处理复杂,会影响事件响应速度。
案例 2:网络请求拦截器(OkHttp 的 Interceptor)
java
// 1. 抽象处理者:Interceptor
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
}
}
// 2. 具体处理者:日志拦截器
public class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 预处理:记录请求日志
System.out.println("发送请求: " + request.url());
// 传递给下一个拦截器
Response response = chain.proceed(request);
// 后处理:记录响应日志
System.out.println("收到响应: " + response.code());
return response;
}
}
// 3. 具体处理者:缓存拦截器
public class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 预处理:检查缓存
Response cacheResponse = getCache(request);
if (cacheResponse != null) {
return cacheResponse; // 有缓存,直接返回,不传递
}
// 传递给下一个拦截器
Response networkResponse = chain.proceed(request);
// 后处理:保存缓存
saveCache(request, networkResponse);
return networkResponse;
}
private Response getCache(Request request) {
// 实际中从缓存获取响应
return null;
}
private void saveCache(Request request, Response response) {
// 实际中保存响应到缓存
}
}
// 4. 链条管理者:OkHttpClient
public class OkHttpClient {
private final List<Interceptor> interceptors = new ArrayList<>();
public OkHttpClient addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
return this;
}
public Response execute(Request request) throws IOException {
// 创建责任链
RealInterceptorChain chain = new RealInterceptorChain(
interceptors, request, 0);
return chain.proceed(request);
}
}
// 5. 责任链实现
public class RealInterceptorChain implements Interceptor.Chain {
private final List<Interceptor> interceptors;
private final Request request;
private final int index;
public RealInterceptorChain(List<Interceptor> interceptors, Request request, int index) {
this.interceptors = interceptors;
this.request = request;
this.index = index;
}
@Override
public Request request() {
return request;
}
@Override
public Response proceed(Request request) throws IOException {
if (index >= interceptors.size()) {
// 所有拦截器处理完毕,执行真正的网络请求
return new NetworkInterceptor().intercept(this);
}
// 获取当前拦截器并调用
Interceptor interceptor = interceptors.get(index);
RealInterceptorChain next = new RealInterceptorChain(
interceptors, request, index + 1);
return interceptor.intercept(next);
}
}
// 6. 使用方式
OkHttpClient client = new OkHttpClient()
.addInterceptor(new LoggingInterceptor())
.addInterceptor(new CacheInterceptor());
Request request = new Request.Builder()
.url("https://api.example.com/data")
.build();
Response response = client.execute(request);
优点:
-
功能插拔灵活:可随时添加 / 删除拦截器(如添加 token 拦截器、压缩拦截器);
-
请求处理解耦:每个拦截器专注单一功能(日志、缓存、重试),职责清晰;
-
符合 OkHttp 设计:OkHttp 的拦截器机制是责任链模式的经典应用。
缺点:
- 调试困难:请求处理路径分散在多个拦截器中,出错时难以追踪;
- 性能开销:每个拦截器都会增加请求处理时间,过多拦截器会影响性能。
案例 3:异常处理链(Crash 上报)
java
// 1. 抽象处理者:异常处理器
public abstract class CrashHandler {
protected CrashHandler nextHandler;
public void setNextHandler(CrashHandler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleCrash(Throwable throwable);
// 传递给下一个处理器
protected void passToNext(Throwable throwable) {
if (nextHandler != null) {
nextHandler.handleCrash(throwable);
}
}
}
// 2. 具体处理者:日志记录处理器
public class LoggingCrashHandler extends CrashHandler {
@Override
public void handleCrash(Throwable throwable) {
// 记录日志到文件
Log.e("Crash", "Crash occurred: " + throwable.getMessage());
// 传递给下一个处理器
passToNext(throwable);
}
}
// 3. 具体处理者:Toast提示处理器
public class ToastCrashHandler extends CrashHandler {
private Context context;
public ToastCrashHandler(Context context) {
this.context = context;
}
@Override
public void handleCrash(Throwable throwable) {
// 显示Toast提示用户
Toast.makeText(context, "应用发生异常,即将重启", Toast.LENGTH_SHORT).show();
// 传递给下一个处理器
passToNext(throwable);
}
}
// 4. 具体处理者:上报服务器处理器
public class ReportCrashHandler extends CrashHandler {
@Override
public void handleCrash(Throwable throwable) {
// 上报异常到服务器
new Thread(() -> {
try {
// 实际中发送异常信息到服务器
Log.d("Crash", "Reporting crash to server");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
// 传递给下一个处理器(如果有)
passToNext(throwable);
}
}
// 5. 应用启动时设置全局异常处理器
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 创建异常处理链
CrashHandler loggingHandler = new LoggingCrashHandler();
CrashHandler toastHandler = new ToastCrashHandler(this);
CrashHandler reportHandler = new ReportCrashHandler();
// 组装链条
loggingHandler.setNextHandler(toastHandler);
toastHandler.setNextHandler(reportHandler);
// 设置为全局异常处理器
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
loggingHandler.handleCrash(throwable);
// 最后退出应用
System.exit(1);
});
}
}
优点:
-
分层处理异常:不同处理器处理不同级别异常(日志记录→用户提示→服务器上报);
-
扩展性好:新增处理器(如添加本地存储崩溃信息)不影响现有代码;
-
符合 Android 开发实践:Android 应用中常用责任链处理全局异常。
缺点:
- 异常处理不彻底:如果某个处理器没有正确传递给下一个,可能导致部分处理逻辑丢失;
- 性能问题:每个异常都会触发所有处理器,即使某些处理器不需要处理该异常。
四、责任链模式的适用场景与总结
适用场景:
- 请求需多级处理:如请假审批、事件分发、网络请求拦截;
- 处理者不确定:事先不知道哪个处理者会处理请求,需动态决定;
- 解耦请求与处理:请求者(如 Activity)不需要知道具体谁处理请求;
- 可插拔处理逻辑:如 OkHttp 拦截器,可随时添加 / 删除拦截器。
核心优点:
- 解耦请求与处理:请求者和处理者松耦合,代码更灵活;
- 动态组合处理者:可在运行时动态调整处理链(如添加 / 删除拦截器);
- 符合开闭原则:新增处理者不影响现有代码,只需修改链条;
- 责任明确:每个处理者只负责自己的部分,职责清晰。
核心缺点:
- 请求可能不被处理:如果链条配置不当,请求可能到链尾都没被处理;
- 调试困难:请求处理路径分散在多个处理者中,出错时难以追踪;
- 性能问题:每个请求都要遍历链条,链条过长会影响性能。
Android 中的最佳实践:
-
利用系统责任链:如 Android 事件分发、OkHttp 拦截器,避免重复造轮子;
-
自定义责任链时:
-
确保链条有终止条件(如链尾处理所有未处理的请求);
-
控制链条长度,避免性能问题;
-
使用接口定义处理者,提高代码可维护性(如
Interceptor接口)。
-
责任链模式是 Android 框架的核心设计思想之一,理解它有助于深入掌握事件分发、网络请求、异常处理等关键机制。