1.概念
责任链模式(Chain of Responsibility)是一种行为型设计模式,它将请求的发送者和接收者解耦,允许多个对象按顺序处理同一请求。每个处理者(Handler)决定是否处理请求或传递给链中的下一个处理者
核心思想:
- 构建一条处理链,每个节点独立处理或传递请求。
- 避免请求发送者与接收者直接耦合。
简单的几个字: 顺序,流式处理
2.在Android源码中的应用场景
2.1 事件分发机制
-
场景描述:
ViewGroup
到View
的触摸事件传递。 -
责任链体现:
Activity
→Window
→DecorView
→ViewGroup
→View
。- 每个节点通过
onTouchEvent()
和dispatchTouchEvent()
决定是否处理或传递事件。
-
关键代码:
// ViewGroup.dispatchTouchEvent 简化逻辑
public boolean dispatchTouchEvent(MotionEvent ev) {
for (View child : children) {
if (child.dispatchTouchEvent(ev)) return true; // 子 View 处理则终止
}
return onTouchEvent(ev); // 自身处理
}
2.2 okhttp中的责任链模式的详细分析
-
拦截器链(Interceptor Chain) :
- 请求处理被拆分为多个拦截器(如缓存、重试、网络 I/O)。
- 每个拦截器独立处理请求,并可决定是否传递。
-
工作流程:
// RealInterceptorChain.proceed()
public Response proceed(Request request) throws IOException {
// 1. 获取下一个拦截器
RealInterceptorChain next = new RealInterceptorChain(interceptors, index + 1);
Interceptor interceptor = interceptors.get(index);
// 2. 当前拦截器处理并传递
Response response = interceptor.intercept(next);
return response;
}
- 优势:灵活扩展(如添加自定义日志拦截器),符合开闭原则。
下面是一个简化版的 OkHttp 责任链模式实现,包含 5 大核心拦截器,并清晰地展示了递归调用的过程:
package com.example.design.chain.okhttp;
/**
* @Author pengcaihua
* @Date 17:24
* @describe
*/
import java.util.ArrayList;
import java.util.List;
public class OkHttpChainDemo {
public static void main(String[] args) throws Exception {
// 创建拦截器链
List<Interceptor> interceptors = new ArrayList<>();
interceptors.add(new RetryAndFollowUpInterceptor());
interceptors.add(new BridgeInterceptor());
interceptors.add(new CacheInterceptor());
interceptors.add(new ConnectInterceptor());
interceptors.add(new CallServerInterceptor());
// 创建初始请求
Request request = new Request("https://api.example.com/data");
// 创建责任链并处理请求
RealInterceptorChain chain = new RealInterceptorChain(interceptors, 0, request);
Response response = chain.proceed(request);
System.out.println("\n最终响应: " + response);
}
// 请求类
static class Request {
final String url;
String headers = "";
Request(String url) {
this.url = url;
System.out.println("创建请求: " + url);
}
void addHeader(String header) {
headers += header + "; ";
}
@Override
public String toString() {
return "Request{url='" + url + "', headers=" + headers + "}";
}
}
// 响应类
static class Response {
final Request request;
String body;
String headers = "";
Response(Request request) {
this.request = request;
}
void addHeader(String header) {
headers += header + "; ";
}
void setBody(String body) {
this.body = body;
}
@Override
public String toString() {
return "Response{request=" + request + ", headers=" + headers + ", body='" + body + "'}";
}
}
// 拦截器接口
interface Interceptor {
Response intercept(Chain chain) throws Exception;
}
// 链接口
interface Chain {
Request request();
Response proceed(Request request) throws Exception;
}
// 实际拦截器链实现
static class RealInterceptorChain implements Chain {
private final List<Interceptor> interceptors;
private final int index;
private final Request request;
RealInterceptorChain(List<Interceptor> interceptors, int index, Request request) {
this.interceptors = interceptors;
this.index = index;
this.request = request;
}
@Override
public Request request() {
return request;
}
@Override
public Response proceed(Request request) throws Exception {
// 1. 创建下一个链
RealInterceptorChain next = new RealInterceptorChain(interceptors, index + 1, request);
// 2. 获取当前拦截器
Interceptor interceptor = interceptors.get(index);
// 3. 调用当前拦截器并返回响应
System.out.println("执行: " + interceptor.getClass().getSimpleName() + " | 调用链深度: " + index);
return interceptor.intercept(next);
}
}
// ================ 五大拦截器实现 ================
// 1. 重试和重定向拦截器
static class RetryAndFollowUpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws Exception {
Request request = chain.request();
System.out.println(" → [Retry] 预处理: 添加重试机制");
// 添加用户代理头
request.addHeader("User-Agent: OkHttp");
// 递归调用下一个拦截器
System.out.println(" → [Retry] 调用下一个拦截器");
Response response = chain.proceed(request);
// 后处理:处理重定向
System.out.println(" ← [Retry] 后处理: 检查重定向");
if (response.body != null && response.body.contains("redirect")) {
System.out.println(" ! [Retry] 检测到重定向");
}
return response;
}
}
// 2. 桥接拦截器
static class BridgeInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws Exception {
Request request = chain.request();
System.out.println(" → [Bridge] 预处理: 添加必要头部");
// 添加必要头信息
request.addHeader("Accept-Language: zh-CN");
request.addHeader("Connection: keep-alive");
System.out.println(" → [Bridge] 调用下一个拦截器");
Response response = chain.proceed(request);
System.out.println(" ← [Bridge] 后处理: 解压响应体");
// 模拟解压响应
if (response.body != null) {
response.setBody(response.body.replace("(compressed)", ""));
}
return response;
}
}
// 3. 缓存拦截器
static class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws Exception {
Request request = chain.request();
System.out.println(" → [Cache] 预处理: 检查缓存");
// 检查缓存
if (request.url.contains("cached")) {
System.out.println(" √ [Cache] 找到缓存,直接返回");
Response cachedResponse = new Response(request);
cachedResponse.setBody("缓存数据");
return cachedResponse;
}
System.out.println(" → [Cache] 未找到缓存,调用下一个拦截器");
Response response = chain.proceed(request);
System.out.println(" ← [Cache] 后处理: 缓存响应");
// 模拟缓存响应
if (response.body != null && response.body.length() < 100) {
System.out.println(" √ [Cache] 缓存响应数据");
}
return response;
}
}
// 4. 连接拦截器
static class ConnectInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws Exception {
Request request = chain.request();
System.out.println(" → [Connect] 预处理: 建立连接");
// 建立连接
System.out.println(" √ [Connect] 连接到: " + request.url);
System.out.println(" → [Connect] 调用下一个拦截器");
Response response = chain.proceed(request);
System.out.println(" ← [Connect] 后处理: 释放连接资源");
// 模拟释放资源
System.out.println(" √ [Connect] 连接已关闭");
return response;
}
}
// 5. 请求服务拦截器
static class CallServerInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws Exception {
Request request = chain.request();
System.out.println(" → [CallServer] 预处理: 发送网络请求");
// 模拟网络请求
System.out.println(" √ [CallServer] 发送请求到服务器");
// 创建响应 - 这是递归的终点
Response response = new Response(request);
response.addHeader("Content-Type: application/json");
response.addHeader("Server: Nginx");
response.setBody("(compressed)服务器响应数据");
System.out.println(" ← [CallServer] 返回响应 (递归终点)");
return response;
}
}
}
okhttp责任链模式的架构图:
2.3 Arounter中的责任链模式
- 场景:路由跳转前的拦截逻辑(如登录验证、权限检查)。
-
实现:
- 定义
IInterceptor
接口,实现process()
方法。 - 拦截器按优先级排序,依次执行。
- 定义
工作流程:
- 关键代码:
// 拦截器接口
public interface IInterceptor {
void process(Postcard postcard, InterceptorCallback callback);
}
// 责任链执行
for (IInterceptor interceptor : sortedInterceptors) {
interceptor.process(postcard, new InterceptorCallback() {
@Override
public void onContinue(Postcard postcard) {
// 继续传递
}
@Override
public void onInterrupt(Throwable exception) {
// 中断跳转
}
});
}
**应用场景**:全局登录拦截器:
@Interceptor(priority = 1)
public class LoginInterceptor implements IInterceptor {
@Override
public void process(Postcard postcard, InterceptorCallback callback) {
if (isLogin() || postcard.getPath().equals("/login")) {
callback.onContinue(postcard); // 已登录或前往登录页 → 放行
} else {
callback.onInterrupt(new RuntimeException("未登录"));
}
}
}
3.UML图
4.语音项目的例子和没用设计模式的对比
语音降噪处理流水线
场景:专业级语音降噪需要多级处理 流程图:
责任链模式通常有两种处理流程实现方式:
单向传递(非递归返回)
public class NonChainAudioProcessing {
// 处理上下文
static class ProcessingContext {
int depth = 0; // 当前调用深度
boolean terminated = false;
String terminationReason;
void enterProcessor(String name) {
System.out.println(indent(depth) + "→ 进入 " + name);
depth++;
}
void exitProcessor(String name) {
depth--;
System.out.println(indent(depth) + "← 返回 " + name);
}
void terminate(String reason) {
terminated = true;
terminationReason = reason;
}
private String indent(int level) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < level; i++) {
sb.append(" "); // 每次添加两个空格
}
return sb.toString();
}
}
// 音频数据结构
static class AudioData {
double snr;
StringBuilder history = new StringBuilder();
AudioData(double snr) {
this.snr = snr;
}
void applyFilter(String name, double improvement) {
snr += improvement;
history.append(indent(context.depth)).append("├─ ")
.append(name).append(" (+").append(improvement).append(" dB)\n");
}
private String indent(int level) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < level; i++) {
sb.append(" "); // 每次添加两个空格
}
return sb.toString();
}
@Override
public String toString() {
return "音频数据 [SNR: " + snr + " dB]\n处理历史:\n" + history.toString();
}
}
// 处理上下文实例
private static ProcessingContext context = new ProcessingContext();
public static void main(String[] args) {
System.out.println("========= 专业语音降噪处理 =========");
AudioData audio = new AudioData(10.0); // 初始信噪比10dB
// 非责任链的递归处理流程
audio = processAudio(audio);
System.out.println("\n最终结果:");
System.out.println(audio);
if (context.terminated) {
System.out.println("处理中断原因: " + context.terminationReason);
}
}
// 核心递归处理函数
private static AudioData processAudio(AudioData input) {
// 1. 环境噪声检测
context.enterProcessor("环境噪声检测");
input = processNoiseDetection(input);
if (context.terminated) {
context.exitProcessor("环境噪声检测");
return input;
}
// 2. 回声消除
context.enterProcessor("回声消除");
input = processEchoCancellation(input);
if (context.terminated) {
context.exitProcessor("回声消除");
context.exitProcessor("环境噪声检测");
return input;
}
// 3. 频谱降噪
context.enterProcessor("频谱降噪");
input = processSpectralReduction(input);
if (context.terminated) {
context.exitProcessor("频谱降噪");
context.exitProcessor("回声消除");
context.exitProcessor("环境噪声检测");
return input;
}
// 4. 语音增强
context.enterProcessor("语音增强");
input = processVoiceEnhancement(input);
// 5. 动态范围压缩
context.enterProcessor("动态范围压缩");
input = processDynamicCompression(input);
context.exitProcessor("动态范围压缩");
// 递归返回过程
context.exitProcessor("语音增强");
context.exitProcessor("频谱降噪");
context.exitProcessor("回声消除");
context.exitProcessor("环境噪声检测");
return input;
}
// 具体处理器实现
private static AudioData processNoiseDetection(AudioData input) {
input.applyFilter("环境噪声检测", 5.0);
// 简单降噪后质量检查
if (input.snr > 25.0) {
context.terminate("高质量音频跳过后续处理");
}
return input;
}
private static AudioData processEchoCancellation(AudioData input) {
input.applyFilter("回声消除", 8.0);
// 在回声消除阶段的中断检查
if (input.snr > 35.0) {
context.terminate("回声消除后音频质量达标");
}
return input;
}
private static AudioData processSpectralReduction(AudioData input) {
input.applyFilter("频谱降噪", 12.0);
return input;
}
private static AudioData processVoiceEnhancement(AudioData input) {
input.applyFilter("语音增强", 7.0);
return input;
}
private static AudioData processDynamicCompression(AudioData input) {
input.applyFilter("动态范围压缩", 3.0);
return input;
}
}
日志:
2025-07-07 16:56:00.915 19672-19672 System.out com.evenbus.myapplication I ========= 专业语音降噪处理 =========
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I → 进入 环境噪声检测
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I → 进入 回声消除
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I → 进入 频谱降噪
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I → 进入 语音增强
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I → 进入 动态范围压缩
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ← 返回 动态范围压缩
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ← 返回 语音增强
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ← 返回 频谱降噪
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ← 返回 回声消除
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ← 返回 环境噪声检测
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I 最终结果:
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I 音频数据 [SNR: 45.0 dB]
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I 处理历史:
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ├─ 环境噪声检测 (+5.0 dB)
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ├─ 回声消除 (+8.0 dB)
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ├─ 频谱降噪 (+12.0 dB)
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ├─ 语音增强 (+7.0 dB)
2025-07-07 16:56:00.916 19672-19672 System.out com.evenbus.myapplication I ├─ 动态范围压缩 (+3.0 dB)
递归返回(双向处理)
4.1 不使用责任链模式
不用责任链模式的架构图 :
4.2 使用责任链模式
// ====================== 核心数据结构 ======================
public class AudioData {
private String rawData;
private double snr; // 信噪比
private double[] frequencySpectrum;
private boolean processed = false;
private String processingHistory = "";
public AudioData(String rawData) {
this.rawData = rawData;
this.snr = 10.0; // 初始信噪比
}
public void applyFilter(String filterName, double snrImprovement) {
this.snr += snrImprovement;
this.processed = true;
processingHistory += " → " + filterName + " (+" + snrImprovement + " dB)";
}
public AudioData applyFilter(String filterName) {
// 模拟处理效果
System.out.println(" ├─ 应用滤波器: " + filterName);
// 根据滤波器类型更新状态
switch (filterName) {
case "环境噪声检测":
this.snr += 5.0;
break;
case "回声消除":
this.snr += 8.0;
break;
case "频谱降噪":
this.snr += 12.0;
break;
case "语音增强":
this.snr += 7.0;
break;
case "动态范围压缩":
this.snr += 3.0;
break;
case "风噪抑制":
this.snr += 6.0;
break;
}
this.processed = true;
return this;
}
public double getSNR() {
return snr;
}
public String getStatus() {
return processed ? "[已处理] SNR: " + String.format("%.1f", snr) + " dB" : "[原始数据]";
}
@Override
public String toString() {
return "音频数据 " + getStatus();
}
}
// ====================== 高级处理链构建器 ======================
class AudioProcessingChainBuilder {
private AudioProcessor first;
private AudioProcessor current; // 是最后一个
public AudioProcessingChainBuilder addProcessor(AudioProcessor processor) {
if (first == null) {
first = processor;
current = processor;
} else {
current.setNext(processor);
current = processor;
}
return this;
}
public AudioProcessor build() { // 拿到第一个
return first;
}
}
// ====================== 抽象处理器 ======================
abstract class AudioProcessor {
protected AudioProcessor next;
public void setNext(AudioProcessor next) {
this.next = next;
}
public AudioProcessor getNext() {
return next;
}
public AudioData process(AudioData input, ProcessingContext context) {
System.out.println("→ 进入 " + getProcessorName());
// 1. 预处理
AudioData preprocessed = preProcess(input, context);
context.log("预处理完成: " + preprocessed);
AudioData result = preprocessed;
// 2. 传递给下一个处理器(如果存在且未中断)
if (next != null && !context.shouldTerminate()) {
context.log("传递给下一处理器: " + next.getProcessorName());
result = next.process(preprocessed, context);
}
// 3. 后处理(递归返回阶段)
if (!context.shouldTerminate()) {
AudioData postprocessed = postProcess(result, context);
context.log("后处理完成: " + postprocessed);
System.out.println("← 返回 " + getProcessorName() + " | " + postprocessed);
return postprocessed;
}
System.out.println("← 返回 " + getProcessorName() + " [已中断] | " + result);
return result;
}
protected AudioData preProcess(AudioData input, ProcessingContext context) {
// 默认不进行预处理
return input;
}
protected AudioData postProcess(AudioData input, ProcessingContext context) {
// 默认不进行后处理
return input;
}
public abstract String getProcessorName();
}
class DynamicRangeCompressor extends AudioProcessor {
@Override
public String getProcessorName() {
return "动态范围压缩";
}
@Override
protected AudioData preProcess(AudioData input, ProcessingContext context) {
// 根据音乐/语音类型调整压缩强度
String audioType = context.get("audioType", String.class);
String filter = "动态范围压缩";
if ("music".equals(audioType)) {
filter = "音乐优化压缩";
} else if ("voice".equals(audioType)) {
filter = "语音优化压缩";
}
return input.applyFilter(filter);
}
@Override
protected AudioData postProcess(AudioData input, ProcessingContext context) {
// 收集最终指标
double originalSNR = context.get("originalSNR", Double.class);
double finalSNR = input.getSNR();
double improvement = finalSNR - originalSNR;
context.log("处理完成!总信噪比提升: " + String.format("%.1f", improvement) + " dB");
context.put("finalSNR", finalSNR);
context.put("totalImprovement", improvement);
return input;
}
}
class EchoCancellationProcessor extends AudioProcessor {
@Override
public String getProcessorName() {
return "回声消除";
}
@Override
protected AudioData preProcess(AudioData input, ProcessingContext context) {
AudioData processed = input.applyFilter("回声消除");
// 检查是否高质量音频(跳过后续处理)
if (processed.getSNR() > 40.0) {
context.terminate("高质量音频跳过后续处理");
context.log("检测到高质量音频 (SNR: " + processed.getSNR() + " dB),跳过后续处理");
}
return processed;
}
@Override
protected AudioData postProcess(AudioData input, ProcessingContext context) {
// 后处理:轻微增强处理后的音频
if (input.getSNR() > 25.0) {
context.log("应用回声消除后增强");
return input.applyFilter("轻微增强");
}
return input;
}
}
// ====================== 具体处理器实现 ======================
class NoiseDetectionProcessor extends AudioProcessor {
@Override
public String getProcessorName() {
return "环境噪声检测";
}
@Override
protected AudioData preProcess(AudioData input, ProcessingContext context) {
context.put("originalSNR", input.getSNR());
return input.applyFilter("环境噪声检测");
}
@Override
protected AudioData postProcess(AudioData input, ProcessingContext context) {
double originalSNR = context.get("originalSNR", Double.class);
double improvement = input.getSNR() - originalSNR;
context.log("噪声检测完成,信噪比提升: " + String.format("%.1f", improvement) + " dB");
return input;
}
}
public class ProcessingContext {
private Map<String, Object> metadata = new HashMap<>();
private boolean terminated = false;
private String terminationReason;
private Deque<String> callStack = new ArrayDeque<>();
public void put(String key, Object value) {
metadata.put(key, value);
}
public <T> T get(String key, Class<T> type) {
return type.cast(metadata.get(key));
}
public void terminate(String reason) {
terminated = true;
terminationReason = reason;
}
public boolean isTerminated() {
return terminated;
}
public String getTerminationReason() {
return terminationReason;
}
public void pushProcessor(String processorName) {
callStack.push(processorName);
System.out.println("→ 进入 " + processorName);
}
public void popProcessor(String processorName) {
String popped = callStack.pop();
if (!popped.equals(processorName)) {
System.out.println("⚠️ 调用栈错误! 期望弹出 " + processorName + " 但实际弹出 " + popped);
}
System.out.println("← 返回 " + processorName);
}
public void log(String message) {
System.out.println(" │ [CONTEXT] " + message);
}
public boolean shouldTerminate() {
return false;
}
}
class SpectralNoiseReducer extends AudioProcessor {
@Override
public String getProcessorName() {
return "频谱降噪";
}
@Override
protected AudioData preProcess(AudioData input, ProcessingContext context) {
// 检测环境类型
String environment = context.get("environment", String.class);
if ("windy".equals(environment)) {
context.log("风噪环境,应用强化降噪");
return input.applyFilter("强化频谱降噪");
}
return input.applyFilter("频谱降噪");
}
@Override
protected AudioData postProcess(AudioData input, ProcessingContext context) {
// 后处理:分析降噪效果
double currentSNR = input.getSNR();
double originalSNR = context.get("originalSNR", Double.class);
if (currentSNR - originalSNR < 15.0) {
context.log("降噪效果不足,应用补偿增强");
return input.applyFilter("补偿增强");
}
return input;
}
}
class VoiceEnhancer extends AudioProcessor {
@Override
public String getProcessorName() {
return "语音增强";
}
@Override
protected AudioData preProcess(AudioData input, ProcessingContext context) {
// 根据设备类型调整增强参数
String deviceType = context.get("deviceType", String.class);
String filter = "语音增强";
if ("headset".equals(deviceType)) {
filter = "耳机优化增强";
} else if ("car".equals(deviceType)) {
filter = "车载环境增强";
}
return input.applyFilter(filter);
}
@Override
protected AudioData postProcess(AudioData input, ProcessingContext context) {
// 后处理:添加元数据
context.put("enhancementApplied", true);
context.put("finalSNRBeforeCompression", input.getSNR());
return input;
}
}
class WindNoiseSuppressor extends AudioProcessor {
@Override
public String getProcessorName() {
return "风噪抑制";
}
@Override
protected AudioData preProcess(AudioData input, ProcessingContext context) {
// 只有在风噪环境中才处理
if ("windy".equals(context.get("environment", String.class))) {
context.log("检测到风噪环境,应用风噪抑制");
return input.applyFilter("风噪抑制");
}
context.log("无风噪环境,跳过处理");
return input;
}
}
// ====================== 客户端使用示例 ======================
public class ProfessionalAudioProcessing {
public static void main(String[] args) {
// 场景1:标准语音处理
System.out.println("==================== 场景1: 标准语音处理 ====================");
processAudioScenario("办公室会议录音", "office", "voice", "built-in");
// // 场景2:风噪环境中的车载处理
// System.out.println("\n==================== 场景2: 风噪环境车载处理 ====================");
// processAudioScenario("车载免提通话", "windy", "voice", "car");
//
// // 场景3:高质量音频跳过处理
// System.out.println("\n==================== 场景3: 高质量音频处理 ====================");
// processHighQualityAudio("录音室高质量音频", "studio", "music", "studio");
}
private static void processAudioScenario(String description, String environment,
String audioType, String deviceType) {
System.out.println("处理: " + description);
System.out.println("环境: " + environment + " | 音频类型: " + audioType + " | 设备: " + deviceType);
// 1. 创建处理链
AudioProcessor chain = new AudioProcessingChainBuilder()
.addProcessor(new NoiseDetectionProcessor())
.addProcessor(new WindNoiseSuppressor()) // 根据环境条件可能跳过
.addProcessor(new EchoCancellationProcessor())
.addProcessor(new SpectralNoiseReducer())
.addProcessor(new VoiceEnhancer())
.addProcessor(new DynamicRangeCompressor())
.build();
// 2. 准备上下文
ProcessingContext context = new ProcessingContext();
context.put("environment", environment);
context.put("audioType", audioType);
context.put("deviceType", deviceType);
// 3. 执行处理
AudioData rawAudio = new AudioData("原始音频数据");
System.out.println("开始处理: " + rawAudio);
AudioData result = chain.process(rawAudio, context);
// 4. 输出结果
System.out.println("\n处理结果: " + result);
if (context.shouldTerminate()) {
System.out.println("! 处理被中断: " + context.getTerminationReason());
}
System.out.println("最终信噪比: " + context.get("finalSNR", Double.class) + " dB");
System.out.println("总提升: " + context.get("totalImprovement", Double.class) + " dB\n");
}
private static void processHighQualityAudio(String description, String environment,
String audioType, String deviceType) {
System.out.println("处理: " + description);
// 创建处理链
AudioProcessor chain = new AudioProcessingChainBuilder()
.addProcessor(new NoiseDetectionProcessor())
.addProcessor(new EchoCancellationProcessor()) // 这里会检测到高质量音频并中断
.addProcessor(new SpectralNoiseReducer())
.build();
// 准备上下文
ProcessingContext context = new ProcessingContext();
context.put("environment", environment);
context.put("audioType", audioType);
context.put("deviceType", deviceType);
// 创建高质量音频(信噪比初始设为45dB)
AudioData highQualityAudio = new AudioData("高质量音频数据") {
@Override
public double getSNR() {
return 45.0; // 高质量音频
}
};
System.out.println("开始处理: " + highQualityAudio);
AudioData result = chain.process(highQualityAudio, context);
System.out.println("\n处理结果: " + result);
System.out.println("! 处理被中断: " + context.getTerminationReason());
System.out.println("最终信噪比: " + highQualityAudio.getSNR() + " dB (保持不变)");
}
}
日志:
2025-07-07 16:39:01.271 16895-16895 System.out com.evenbus.myapplication I ==================== 场景1: 标准语音处理 ====================
2025-07-07 16:39:01.271 16895-16895 System.out com.evenbus.myapplication I 处理: 办公室会议录音
2025-07-07 16:39:01.271 16895-16895 System.out com.evenbus.myapplication I 环境: office | 音频类型: voice | 设备: built-in
2025-07-07 16:39:01.271 16895-16895 System.out com.evenbus.myapplication I 开始处理: 音频数据 [原始数据]
2025-07-07 16:39:01.271 16895-16895 System.out com.evenbus.myapplication I → 进入 环境噪声检测
2025-07-07 16:39:01.271 16895-16895 System.out com.evenbus.myapplication I ├─ 应用滤波器: 环境噪声检测
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 预处理完成: 音频数据 [已处理] SNR: 15.0 dB
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 传递给下一处理器: 风噪抑制
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I → 进入 风噪抑制
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 无风噪环境,跳过处理
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 预处理完成: 音频数据 [已处理] SNR: 15.0 dB
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 传递给下一处理器: 回声消除
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I → 进入 回声消除
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I ├─ 应用滤波器: 回声消除
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 预处理完成: 音频数据 [已处理] SNR: 23.0 dB
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 传递给下一处理器: 频谱降噪
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I → 进入 频谱降噪
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I ├─ 应用滤波器: 频谱降噪
2025-07-07 16:39:01.272 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 预处理完成: 音频数据 [已处理] SNR: 35.0 dB
2025-07-07 16:39:01.273 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 传递给下一处理器: 语音增强
2025-07-07 16:39:01.273 16895-16895 System.out com.evenbus.myapplication I → 进入 语音增强
2025-07-07 16:39:01.273 16895-16895 System.out com.evenbus.myapplication I ├─ 应用滤波器: 语音增强
2025-07-07 16:39:01.273 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 预处理完成: 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.273 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 传递给下一处理器: 动态范围压缩
2025-07-07 16:39:01.273 16895-16895 System.out com.evenbus.myapplication I → 进入 动态范围压缩
2025-07-07 16:39:01.273 16895-16895 System.out com.evenbus.myapplication I ├─ 应用滤波器: 语音优化压缩
2025-07-07 16:39:01.273 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 预处理完成: 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.274 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 处理完成!总信噪比提升: 32.0 dB
2025-07-07 16:39:01.274 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 后处理完成: 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.274 16895-16895 System.out com.evenbus.myapplication I ← 返回 动态范围压缩 | 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.274 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 后处理完成: 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.275 16895-16895 System.out com.evenbus.myapplication I ← 返回 语音增强 | 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.275 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 后处理完成: 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.275 16895-16895 System.out com.evenbus.myapplication I ← 返回 频谱降噪 | 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.275 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 应用回声消除后增强
2025-07-07 16:39:01.275 16895-16895 System.out com.evenbus.myapplication I ├─ 应用滤波器: 轻微增强
2025-07-07 16:39:01.275 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 后处理完成: 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.275 16895-16895 System.out com.evenbus.myapplication I ← 返回 回声消除 | 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.276 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 后处理完成: 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.276 16895-16895 System.out com.evenbus.myapplication I ← 返回 风噪抑制 | 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.276 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 噪声检测完成,信噪比提升: 32.0 dB
2025-07-07 16:39:01.276 16895-16895 System.out com.evenbus.myapplication I │ [CONTEXT] 后处理完成: 音频数据 [已处理] SNR: 42.0 dB
2025-07-07 16:39:01.276 16895-16895 System.out com.evenbus.myapplication I ← 返回 环境噪声检测 | 音频数据 [已处理] SNR: 42.0 dB
用责任链模式的架构图 :
好处
-
新增处理步骤(如
风噪抑制
)需修改process()
方法 开闭原则 新增处理器只需实现AudioProcessor
接口: -
无法动态调整处理顺序(如移动环境下先做风噪抑制) 灵活组合
-
双向处理
- 预处理(添加头信息、缓存检查)
- 后处理(解压响应、缓存存储)
5.优点
- 灵活扩展:通过添加拦截器实现功能扩展(如日志、埋点),无需修改核心代码。
- 动态排序:拦截器优先级(
priority
)可控制执行顺序。 - 单一职责:每个拦截器只关注自身逻辑(如登录验证无需感知权限检查)。
- 流程可控:支持中断跳转(如未登录时拦截并跳转登录页)。
6.和相似的设计模式的区别
组合模式的区别 责任链模式和组合模式虽然都涉及多个对象的协作,但解决的是完全不同的问题:
- 责任链模式关注请求的传递和处理,强调请求在对象链上的流动
- 组合模式关注对象的结构组织,强调部分与整体的层次关系
总结
-
责任链模式适用场景:多步骤处理流程、需动态扩展处理逻辑的模块(如网络请求、路由跳转)。
-
Android 实战要点:
- 优先使用接口定义处理者(如
Interceptor
)。 - 通过
setNext()
方法构建链式关系。 - 结合优先级(如 ARouter 的
priority
)控制执行顺序。
- 优先使用接口定义处理者(如
-
避坑指南:避免循环引用,确保链终结点能处理所有未捕获请求。
项目的地址: github.com/pengcaihua1…