责任链模式是一种行为设计模式,它将请求沿着处理者链进行发送。收到请求后,每个处理者决定处理请求或将其传递给链中的下一个处理者。这种模式使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
责任链模式通过构建处理者对象链来工作,每个处理者包含对下一个处理者的引用。当请求到达时,第一个处理者尝试处理它;如果无法处理,则将请求传递给链中的下一个处理者,以此类推,直到请求被处理或链结束。
这种模式特别适用于处理多种条件判断的场景,通过将每个条件封装到独立的处理类中,避免了复杂的条件语句嵌套,使代码更加清晰和可维护。处理者可以在运行时动态添加或移除,增强了系统的灵活性。
员工请假需要经过不同级别的管理者审批,根据请假天数决定由谁来审批。
// 请假请求类
class LeaveRequest {
private String employeeName;
private int leaveDays;
public LeaveRequest(String employeeName, int leaveDays) {
this.employeeName = employeeName;
this.leaveDays = leaveDays;
}
public String getEmployeeName() { return employeeName; }
public int getLeaveDays() { return leaveDays; }
}
// 抽象处理者
abstract class Approver {
protected Approver successor; // 后继者
protected String name;
public Approver(String name) {
this.name = name;
}
// 设置后继者
public void setSuccessor(Approver successor) {
this.successor = successor;
}
// 处理请求的抽象方法
public abstract void processRequest(LeaveRequest request);
}
// 主管 - 可以批准1-3天的请假
class Director extends Approver {
public Director(String name) {
super(name);
}
@Override
public void processRequest(LeaveRequest request) {
if (request.getLeaveDays() <= 3) {
System.out.println(name + " 批准了 " + request.getEmployeeName() +
" 的 " + request.getLeaveDays() + " 天请假申请");
} else if (successor != null) {
// 转发给经理
successor.processRequest(request);
}
}
}
// 经理 - 可以批准4-7天的请假
class Manager extends Approver {
public Manager(String name) {
super(name);
}
@Override
public void processRequest(LeaveRequest request) {
if (request.getLeaveDays() <= 7) {
System.out.println(name + " 批准了 " + request.getEmployeeName() +
" 的 " + request.getLeaveDays() + " 天请假申请");
} else if (successor != null) {
// 转发给总监
successor.processRequest(request);
}
}
}
// 总监 - 可以批准8-14天的请假
class GeneralManager extends Approver {
public GeneralManager(String name) {
super(name);
}
@Override
public void processRequest(LeaveRequest request) {
if (request.getLeaveDays() <= 14) {
System.out.println(name + " 批准了 " + request.getEmployeeName() +
" 的 " + request.getLeaveDays() + " 天请假申请");
} else {
System.out.println("请假天数过长,拒绝申请!");
}
}
}
// 客户端代码
public class LeaveApprovalDemo {
public static void main(String[] args) {
// 创建处理者
Approver director = new Director("张主管");
Approver manager = new Manager("王经理");
Approver generalManager = new GeneralManager("李总监");
// 组建责任链
director.setSuccessor(manager);
manager.setSuccessor(generalManager);
// 创建请假请求并发送
LeaveRequest request1 = new LeaveRequest("小明", 2);
LeaveRequest request2 = new LeaveRequest("小红", 5);
LeaveRequest request3 = new LeaveRequest("小李", 10);
LeaveRequest request4 = new LeaveRequest("小张", 20);
// 处理请求
director.processRequest(request1); // 张主管处理
director.processRequest(request2); // 王经理处理
director.processRequest(request3); // 李总监处理
director.processRequest(request4); // 拒绝申请
}
}
张主管 批准了 小明 的 2 天请假申请 王经理 批准了 小红 的 5 天请假申请 李总监 批准了 小李 的 10 天请假申请 请假天数过长,拒绝申请!
根据日志级别将消息输出到不同的目标(控制台、文件、数据库等)。
# 定义日志级别
class LogLevel:
INFO = 1
DEBUG = 2
ERROR = 3
# 抽象日志处理者
class Logger:
def __init__(self, level):
self.level = level
self.next_logger = None
# 设置下一个处理者
def set_next_logger(self, next_logger):
self.next_logger = next_logger
return next_logger # 返回下一个处理者,便于链式调用
# 处理日志请求
def log_message(self, level, message):
if self.level <= level:
self.write(message)
# 传递给下一个处理者
if self.next_logger is not None:
self.next_logger.log_message(level, message)
# 由子类实现的写日志方法
def write(self, message):
pass
# 控制台日志处理者
class ConsoleLogger(Logger):
def write(self, message):
print(f"控制台日志: {message}")
# 文件日志处理者
class FileLogger(Logger):
def write(self, message):
print(f"文件日志: {message}") # 实际应用中会写入文件
# 错误日志处理者
class ErrorLogger(Logger):
def write(self, message):
print(f"错误日志: {message}") # 实际应用中可能会发送邮件或短信通知
# 客户端代码
def get_logger_chain():
# 创建处理者
console_logger = ConsoleLogger(LogLevel.INFO) # 处理所有级别
file_logger = FileLogger(LogLevel.DEBUG) # 处理DEBUG及以上级别
error_logger = ErrorLogger(LogLevel.ERROR) # 只处理ERROR级别
# 构建责任链
console_logger.set_next_logger(file_logger).set_next_logger(error_logger)
return console_logger
# 使用日志链
if __name__ == "__main__":
logger_chain = get_logger_chain()
# 记录不同级别的日志
print("记录INFO级别日志:")
logger_chain.log_message(LogLevel.INFO, "这是一条信息日志")
print("\n记录DEBUG级别日志:")
logger_chain.log_message(LogLevel.DEBUG, "这是一条调试日志")
print("\n记录ERROR级别日志:")
logger_chain.log_message(LogLevel.ERROR, "这是一条错误日志")
记录INFO级别日志: 控制台日志: 这是一条信息日志 记录DEBUG级别日志: 控制台日志: 这是一条调试日志 文件日志: 这是一条调试日志 记录ERROR级别日志: 控制台日志: 这是一条错误日志 文件日志: 这是一条错误日志 错误日志: 这是一条错误日志
HTTP请求经过一系列过滤器处理,如认证、授权、日志记录、数据压缩等。
// 请求对象
class Request {
constructor(url, method, headers = {}, body = null) {
this.url = url;
this.method = method;
this.headers = headers;
this.body = body;
this.user = null; // 认证后的用户信息
}
}
// 响应对象
class Response {
constructor() {
this.status = 200;
this.headers = {};
this.body = null;
}
setStatus(status) {
this.status = status;
return this;
}
setBody(body) {
this.body = body;
return this;
}
}
// 过滤器接口
class Filter {
constructor() {
this.next = null;
}
setNext(filter) {
this.next = filter;
return filter; // 返回下一个过滤器,便于链式调用
}
// 处理请求
process(request, response) {
// 子类实现具体处理逻辑
// 如果有下一个过滤器,则传递给它
if (this.next) {
return this.next.process(request, response);
}
return response; // 返回最终响应
}
}
// 日志过滤器
class LoggingFilter extends Filter {
process(request, response) {
console.log(`[日志] ${new Date().toISOString()} - ${request.method} ${request.url}`);
// 调用下一个过滤器
if (this.next) {
return this.next.process(request, response);
}
return response;
}
}
// 认证过滤器
class AuthenticationFilter extends Filter {
process(request, response) {
console.log('[认证] 验证用户身份');
// 检查认证头
if (!request.headers.authorization) {
console.log('[认证] 未提供认证信息');
return response.setStatus(401).setBody({ error: '未授权访问' });
}
// 模拟认证逻辑
if (request.headers.authorization === 'Bearer valid-token') {
request.user = { id: 123, name: '张三', role: 'user' };
console.log(`[认证] 用户已认证: ${request.user.name}`);
// 继续处理
if (this.next) {
return this.next.process(request, response);
}
} else {
console.log('[认证] 无效的认证令牌');
return response.setStatus(401).setBody({ error: '无效的认证令牌' });
}
return response;
}
}
// 授权过滤器
class AuthorizationFilter extends Filter {
process(request, response) {
console.log('[授权] 检查访问权限');
// 检查用户是否已认证
if (!request.user) {
return response.setStatus(401).setBody({ error: '未授权访问' });
}
// 检查是否有权限访问特定资源
if (request.url.startsWith('/admin') && request.user.role !== 'admin') {
console.log('[授权] 权限不足');
return response.setStatus(403).setBody({ error: '权限不足' });
}
console.log('[授权] 权限验证通过');
// 继续处理
if (this.next) {
return this.next.process(request, response);
}
return response;
}
}
// 内容处理过滤器
class ContentProcessingFilter extends Filter {
process(request, response) {
console.log('[内容] 处理请求内容');
// 处理请求内容
if (request.method === 'POST' && request.body) {
console.log('[内容] 处理POST数据');
// 这里可以进行数据验证、转换等操作
}
// 设置响应内容
response.setBody({
message: '请求处理成功',
timestamp: new Date().toISOString(),
user: request.user ? request.user.name : 'Guest'
});
console.log('[内容] 响应内容已生成');
// 继续处理
if (this.next) {
return this.next.process(request, response);
}
return response;
}
}
// 客户端代码
function handleRequest(request) {
// 创建过滤器链
const loggingFilter = new LoggingFilter();
const authFilter = new AuthenticationFilter();
const authzFilter = new AuthorizationFilter();
const contentFilter = new ContentProcessingFilter();
// 构建过滤器链
loggingFilter
.setNext(authFilter)
.setNext(authzFilter)
.setNext(contentFilter);
// 创建响应对象
const response = new Response();
// 处理请求
return loggingFilter.process(request, response);
}
// 测试代码
function runDemo() {
console.log("=== 测试1: 未认证的请求 ===");
const request1 = new Request('/api/data', 'GET');
const response1 = handleRequest(request1);
console.log('响应状态:', response1.status);
console.log('响应内容:', response1.body);
console.log("\n=== 测试2: 认证但权限不足 ===");
const request2 = new Request('/admin/dashboard', 'GET', {
authorization: 'Bearer valid-token'
});
const response2 = handleRequest(request2);
console.log('响应状态:', response2.status);
console.log('响应内容:', response2.body);
console.log("\n=== 测试3: 有效请求 ===");
const request3 = new Request('/api/profile', 'GET', {
authorization: 'Bearer valid-token'
});
const response3 = handleRequest(request3);
console.log('响应状态:', response3.status);
console.log('响应内容:', response3.body);
}
// 运行演示
runDemo();
=== 测试1: 未认证的请求 === [日志] 2023-07-15T10:30:45.123Z - GET /api/data [认证] 验证用户身份 [认证] 未提供认证信息 响应状态: 401 响应内容: { error: '未授权访问' } === 测试2: 认证但权限不足 === [日志] 2023-07-15T10:30:45.125Z - GET /admin/dashboard [认证] 验证用户身份 [认证] 用户已认证: 张三 [授权] 检查访问权限 [授权] 权限不足 响应状态: 403 响应内容: { error: '权限不足' } === 测试3: 有效请求 === [日志] 2023-07-15T10:30:45.127Z - GET /api/profile [认证] 验证用户身份 [认证] 用户已认证: 张三 [授权] 检查访问权限 [授权] 权限验证通过 [内容] 处理请求内容 [内容] 响应内容已生成 响应状态: 200 响应内容: { message: '请求处理成功', timestamp: '2023-07-15T10:30:45.127Z', user: '张三' }
比较维度 | 责任链模式 | 策略模式 | 命令模式 |
---|---|---|---|
核心思想 | 将请求沿着处理者链传递,直到被处理 | 定义一系列算法,使它们可以互相替换 | 将请求封装为对象,支持请求排队、记录和撤销 |
处理方式 | 多个处理者按顺序尝试处理请求 | 一个处理者使用一种策略处理请求 | 发送者通过命令对象调用接收者的方法 |
决策方式 | 每个处理者自行决定是否处理请求 | 客户端选择使用哪种策略 | 命令对象决定如何执行请求 |
扩展性 | 良好,可轻松添加新的处理者 | 良好,可轻松添加新的策略 | 良好,可轻松添加新的命令 |
耦合度 | 低,发送者与接收者完全解耦 | 中,上下文需要了解所有策略 | 低,调用者与接收者解耦 |
适用场景 | 多个对象可以处理请求,但处理者和顺序在运行时确定 | 需要在运行时选择算法的场景 | 需要参数化对象的操作,支持撤销等操作 |
应用场景 | 适用性评分 |
---|---|
审批流程 |
★★★★★ 5/5
|
异常处理 |
★★★★★ 4/5
|
中间件/过滤器 |
★★★★★ 5/5
|
日志记录 |
★★★★★ 4/5
|
简单业务逻辑 |
★★★★★ 2/5
|
虽然两种模式都涉及对象链,但它们的目的不同:
有几种常见的解决方案:
当责任链较长时,可能会导致性能问题。以下是一些优化策略:
有时,我们希望多个处理者都能处理请求的不同部分,这可以通过以下方式实现:
责任链模式在许多流行的框架和系统中都有应用:
每个处理者应该只关注一种类型的请求处理,这样可以使系统更加模块化,易于维护和扩展。
请求对象应包含处理者需要的所有信息,并可能包含处理状态,以便跟踪请求在链中的处理情况。
在链的末尾添加一个默认处理者,确保所有请求都能得到处理,避免请求"丢失"。
设计责任链时,考虑允许在运行时动态添加、移除或重新排序处理者,以提高系统的灵活性。
确保责任链中不会出现循环引用,否则可能导致无限循环和栈溢出。