Android设计模式之责任链模式与使用场景

在 Android 开发中,责任链模式(Chain of Responsibility Pattern)是一种常用的行为型设计模式,其核心思想是将多个请求处理者通过“链”的形式连接起来,使请求沿着链传递,直到被某个处理者处理为止。这种模式能有效降低请求发送者与处理者之间的耦合,让每个处理者只关注自己能处理的请求,同时支持动态扩展处理者。

一、责任链模式的核心角色

责任链模式通常包含以下 3 个核心角色:

  1. 抽象处理者(Handler)
    定义处理请求的接口,包含一个指向“下一个处理者”的引用(即链的连接点),以及处理请求的抽象方法。

  2. 具体处理者(ConcreteHandler)
    实现抽象处理者的接口,负责处理特定类型的请求。如果自身能处理请求,则直接处理;否则将请求传递给“下一个处理者”。

  3. 请求(Request)
    包含需要被处理的信息(如请求类型、参数等),是传递在链中的数据载体。

二、责任链模式的工作流程

  1. 多个具体处理者通过“下一个处理者”的引用形成一条链;
  2. 当一个请求进入链中时,从链的第一个处理者开始尝试处理;
  3. 若当前处理者能处理请求,则直接处理并终止传递;
  4. 若不能处理,则通过引用将请求传递给下一个处理者;
  5. 以此类推,直到请求被处理或到达链的末尾(未被处理)。

三、责任链模式的优缺点

优点:
  • 降低耦合度:请求发送者无需知道具体由哪个处理者处理,只需将请求投入链中即可。
  • 灵活性高:可动态增减处理者或调整链的顺序,符合“开闭原则”。
  • 分工明确:每个处理者只处理自己职责范围内的请求,逻辑清晰。
缺点:
  • 请求可能未被处理:若链中所有处理者都无法处理请求,可能导致请求“丢失”(需提前设计兜底方案)。
  • 性能影响:链过长时,请求传递会增加耗时,影响效率。

四、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 树中,事件从 ActivityViewGroupView 逐层传递(或反向传递)。
  • 处理逻辑:每个 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 事件分发等框架级应用,能帮助我们更灵活地设计自己的业务逻辑(如权限校验链、数据过滤链等)。使用时需注意控制链的长度,避免性能问题,并确保请求有兜底处理方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值