责任链模式:用公司请假流程的故事理解请求传递

55 阅读8分钟

一、故事解说:公司请假流程如何层层审批

假设你在一家公司上班,请假流程如下:

  1. 提交申请:你向直属领导提交请假申请(比如 3 天);

  2. 领导审批

    • 直属领导(组长):只能批 1 天内的假,超过则转给上级;
    • 部门经理:能批 3 天内的假,超过则转给总监;
    • 总监:能批 7 天内的假,超过则转给 CEO;
  3. 最终处理: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 的存在;

  • 灵活定制:可通过重写dispatchTouchEventonTouchEvent改变事件传递规则;

  • 符合 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 应用中常用责任链处理全局异常。

缺点

  • 异常处理不彻底:如果某个处理器没有正确传递给下一个,可能导致部分处理逻辑丢失;
  • 性能问题:每个异常都会触发所有处理器,即使某些处理器不需要处理该异常。

四、责任链模式的适用场景与总结

适用场景

  1. 请求需多级处理:如请假审批、事件分发、网络请求拦截;
  2. 处理者不确定:事先不知道哪个处理者会处理请求,需动态决定;
  3. 解耦请求与处理:请求者(如 Activity)不需要知道具体谁处理请求;
  4. 可插拔处理逻辑:如 OkHttp 拦截器,可随时添加 / 删除拦截器。

核心优点

  • 解耦请求与处理:请求者和处理者松耦合,代码更灵活;
  • 动态组合处理者:可在运行时动态调整处理链(如添加 / 删除拦截器);
  • 符合开闭原则:新增处理者不影响现有代码,只需修改链条;
  • 责任明确:每个处理者只负责自己的部分,职责清晰。

核心缺点

  • 请求可能不被处理:如果链条配置不当,请求可能到链尾都没被处理;
  • 调试困难:请求处理路径分散在多个处理者中,出错时难以追踪;
  • 性能问题:每个请求都要遍历链条,链条过长会影响性能。

Android 中的最佳实践

  • 利用系统责任链:如 Android 事件分发、OkHttp 拦截器,避免重复造轮子;

  • 自定义责任链时

    1. 确保链条有终止条件(如链尾处理所有未处理的请求);

    2. 控制链条长度,避免性能问题;

    3. 使用接口定义处理者,提高代码可维护性(如Interceptor接口)。

责任链模式是 Android 框架的核心设计思想之一,理解它有助于深入掌握事件分发、网络请求、异常处理等关键机制。