定义
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它将请求的发送者和接收者解耦,让多个对象都有机会处理请求。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
责任链模式的核心思想是:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象组成一条链,并沿着这条链传递请求,直到有对象处理它为止。
为什么需要责任链模式
问题场景:假设我们正在开发一个审批系统,不同金额的报销需要不同级别的人员审批。
最直接的方式可能是这样:
class ExpenseApproval {
func approve(amount: Double) {
if amount <= 1000 {
// 组长审批
teamLeaderApprove(amount)
} else if amount <= 5000 {
// 部门经理审批
departmentManagerApprove(amount)
} else if amount <= 10000 {
// 总监审批
directorApprove(amount)
} else {
// CEO审批
ceoApprove(amount)
}
}
func teamLeaderApprove(_ amount: Double) { ... }
func departmentManagerApprove(_ amount: Double) { ... }
func directorApprove(_ amount: Double) { ... }
func ceoApprove(_ amount: Double) { ... }
}
这种方式有什么问题?
- 职责不清:所有审批逻辑都在一个类中,违反单一职责原则
- 难以扩展:新增审批级别需要修改已有代码,违反开闭原则
- 硬编码规则:审批金额限制写死在代码中,难以灵活配置
- 紧耦合:发送者必须知道所有审批者的存在
责任链模式的解决思路:
将每个审批者封装为独立的处理器,组成一条链,请求沿链传递:
// 处理器协议
protocol Approver: AnyObject {
var nextApprover: Approver? { get set }
func approve(expense: Expense) -> ApprovalResult
}
// 组长
class TeamLeader: Approver {
var nextApprover: Approver?
let limit: Double = 1000
func approve(expense: Expense) -> ApprovalResult {
if expense.amount <= limit {
return .approved(by: "Team Leader")
}
// 超出权限,传递给下一个审批者
return nextApprover?.approve(expense: expense) ?? .rejected
}
}
// 部门经理
class DepartmentManager: Approver {
var nextApprover: Approver?
let limit: Double = 5000
func approve(expense: Expense) -> ApprovalResult {
if expense.amount <= limit {
return .approved(by: "Department Manager")
}
return nextApprover?.approve(expense: expense) ?? .rejected
}
}
// 构建责任链
let teamLeader = TeamLeader()
let manager = DepartmentManager()
let director = Director()
let ceo = CEO()
teamLeader.nextApprover = manager
manager.nextApprover = director
director.nextApprover = ceo
// 使用 - 请求自动沿链传递
let expense = Expense(amount: 3000, description: "Conference fee")
let result = teamLeader.approve(expense: expense)
// 自动传递到DepartmentManager处理
责任链模式的好处:
- 解耦发送者和接收者:发送者不需要知道具体由谁处理
- 灵活配置:可以动态调整链的结构和顺序
- 单一职责:每个处理器只负责自己能处理的请求
- 易于扩展:新增处理器只需实现协议并加入链中
模式结构
classDiagram
class Handler {
<<abstract>>
-nextHandler: Handler
+setNext(handler: Handler)
+handle(request: Request)
}
class ConcreteHandlerA {
+handle(request: Request)
}
class ConcreteHandlerB {
+handle(request: Request)
}
class ConcreteHandlerC {
+handle(request: Request)
}
class Client {
+sendRequest(request: Request)
}
Handler <|-- ConcreteHandlerA
Handler <|-- ConcreteHandlerB
Handler <|-- ConcreteHandlerC
Handler --> Handler : nextHandler
Client --> Handler
请求处理流程:
flowchart LR
Client --> A[Handler A]
A -->|无法处理| B[Handler B]
B -->|无法处理| C[Handler C]
C -->|处理完成| Result
iOS中的应用
1. 响应者链(Responder Chain)
iOS中最经典的责任链模式应用就是响应者链。事件从第一响应者开始,沿着响应者链传递,直到找到能够处理的对象。
// iOS响应者链示例
class CustomButton: UIButton {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("CustomButton received touch")
// 可以选择处理或传递给下一个响应者
if shouldHandleTouch(touches) {
handleTouch(touches)
} else {
// 传递给下一个响应者
super.touchesBegan(touches, with: event)
}
}
private func shouldHandleTouch(_ touches: Set<UITouch>) -> Bool {
return true
}
private func handleTouch(_ touches: Set<UITouch>) {
print("CustomButton handling touch")
}
}
class CustomView: UIView {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("CustomView received touch")
super.touchesBegan(touches, with: event)
}
}
class CustomViewController: UIViewController {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("CustomViewController received touch")
super.touchesBegan(touches, with: event)
}
}
响应者链的结构:
flowchart TD
A[First Responder] --> B[UIView]
B --> C[Superview]
C --> D[UIViewController]
D --> E[UIWindow]
E --> F[UIApplication]
F --> G[AppDelegate]
2. 手势识别责任链
// 手势处理责任链
protocol GestureHandler: AnyObject {
var nextHandler: GestureHandler? { get set }
func handleGesture(_ gesture: UIGestureRecognizer) -> Bool
}
class TapGestureHandler: GestureHandler {
var nextHandler: GestureHandler?
func handleGesture(_ gesture: UIGestureRecognizer) -> Bool {
if let tap = gesture as? UITapGestureRecognizer {
print("Handling tap gesture with \(tap.numberOfTapsRequired) taps")
return true
}
return nextHandler?.handleGesture(gesture) ?? false
}
}
class SwipeGestureHandler: GestureHandler {
var nextHandler: GestureHandler?
func handleGesture(_ gesture: UIGestureRecognizer) -> Bool {
if let swipe = gesture as? UISwipeGestureRecognizer {
print("Handling swipe gesture in direction: \(swipe.direction)")
return true
}
return nextHandler?.handleGesture(gesture) ?? false
}
}
class PanGestureHandler: GestureHandler {
var nextHandler: GestureHandler?
func handleGesture(_ gesture: UIGestureRecognizer) -> Bool {
if let pan = gesture as? UIPanGestureRecognizer {
let translation = pan.translation(in: pan.view)
print("Handling pan gesture with translation: \(translation)")
return true
}
return nextHandler?.handleGesture(gesture) ?? false
}
}
class DefaultGestureHandler: GestureHandler {
var nextHandler: GestureHandler?
func handleGesture(_ gesture: UIGestureRecognizer) -> Bool {
print("Default handler: unrecognized gesture")
return false
}
}
3. 网络请求拦截器链
// 请求上下文
class RequestContext {
var request: URLRequest
var response: URLResponse?
var data: Data?
var error: Error?
init(request: URLRequest) {
self.request = request
}
}
// 拦截器协议
protocol Interceptor: AnyObject {
var nextInterceptor: Interceptor? { get set }
func intercept(_ context: RequestContext) async throws -> RequestContext
}
extension Interceptor {
@discardableResult
func setNext(_ interceptor: Interceptor) -> Interceptor {
self.nextInterceptor = interceptor
return interceptor
}
}
// 认证拦截器
class AuthInterceptor: Interceptor {
var nextInterceptor: Interceptor?
private let tokenProvider: () -> String?
init(tokenProvider: @escaping () -> String?) {
self.tokenProvider = tokenProvider
}
func intercept(_ context: RequestContext) async throws -> RequestContext {
if let token = tokenProvider() {
context.request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
}
return try await nextInterceptor?.intercept(context) ?? context
}
}
// 日志拦截器
class LoggingInterceptor: Interceptor {
var nextInterceptor: Interceptor?
func intercept(_ context: RequestContext) async throws -> RequestContext {
let startTime = Date()
print("Request: \(context.request.httpMethod ?? "GET") \(context.request.url?.absoluteString ?? "")")
let result = try await nextInterceptor?.intercept(context) ?? context
let duration = Date().timeIntervalSince(startTime)
print("Response: \(duration * 1000)ms")
return result
}
}
// 重试拦截器
class RetryInterceptor: Interceptor {
var nextInterceptor: Interceptor?
let maxRetries: Int
init(maxRetries: Int = 3) {
self.maxRetries = maxRetries
}
func intercept(_ context: RequestContext) async throws -> RequestContext {
var lastError: Error?
for attempt in 0..<maxRetries {
do {
return try await nextInterceptor?.intercept(context) ?? context
} catch {
lastError = error
print("Retry attempt \(attempt + 1) failed: \(error)")
// 等待后重试
try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(attempt)) * 1_000_000_000))
}
}
throw lastError ?? URLError(.unknown)
}
}
// 缓存拦截器
class CacheInterceptor: Interceptor {
var nextInterceptor: Interceptor?
private let cache = NSCache<NSString, NSData>()
func intercept(_ context: RequestContext) async throws -> RequestContext {
let cacheKey = context.request.url?.absoluteString ?? ""
// 检查缓存
if context.request.httpMethod == "GET",
let cachedData = cache.object(forKey: cacheKey as NSString) {
context.data = cachedData as Data
return context
}
let result = try await nextInterceptor?.intercept(context) ?? context
// 缓存结果
if context.request.httpMethod == "GET",
let data = result.data {
cache.setObject(data as NSData, forKey: cacheKey as NSString)
}
return result
}
}
// 实际请求执行器
class NetworkExecutor: Interceptor {
var nextInterceptor: Interceptor?
func intercept(_ context: RequestContext) async throws -> RequestContext {
let (data, response) = try await URLSession.shared.data(for: context.request)
context.data = data
context.response = response
return context
}
}
// 网络客户端
class NetworkClient {
private let interceptorChain: Interceptor
init() {
// 构建拦截器链
let auth = AuthInterceptor { "user_token" }
let logging = LoggingInterceptor()
let retry = RetryInterceptor(maxRetries: 3)
let cache = CacheInterceptor()
let executor = NetworkExecutor()
auth
.setNext(logging)
.setNext(retry)
.setNext(cache)
.setNext(executor)
interceptorChain = auth
}
func execute(_ request: URLRequest) async throws -> Data {
let context = RequestContext(request: request)
let result = try await interceptorChain.intercept(context)
if let error = result.error {
throw error
}
return result.data ?? Data()
}
}
责任链模式的变体
纯责任链与不纯责任链
纯责任链:请求只能被一个处理者处理
protocol PureHandler {
var nextHandler: PureHandler? { get set }
func handle(_ request: Request) -> Bool
}
class ConcreteHandler: PureHandler {
var nextHandler: PureHandler?
func handle(_ request: Request) -> Bool {
if canHandle(request) {
// 处理请求,不再传递
return true
}
// 传递给下一个处理者
return nextHandler?.handle(request) ?? false
}
func canHandle(_ request: Request) -> Bool {
return false
}
}
不纯责任链:请求可以被多个处理者处理
protocol ImpureHandler {
var nextHandler: ImpureHandler? { get set }
func handle(_ request: Request)
}
class ConcreteImpureHandler: ImpureHandler {
var nextHandler: ImpureHandler?
func handle(_ request: Request) {
// 处理请求
process(request)
// 继续传递给下一个处理者
nextHandler?.handle(request)
}
func process(_ request: Request) {
// 处理逻辑
}
}
优缺点
优点
- 解耦发送者与接收者:发送者不需要知道具体的处理者
- 灵活性:可以动态调整责任链的结构和顺序
- 单一职责:每个处理者只负责自己能处理的请求
- 可扩展:新增处理者不影响现有代码
缺点
- 不保证被处理:请求可能到达链尾都没有处理者
- 调试困难:链较长时,调试和追踪比较困难
- 性能开销:请求可能需要遍历整个链
- 循环引用风险:如果链配置错误,可能形成循环
最佳实践
- 设置默认处理者:在链尾设置一个默认处理者,确保请求被处理
- 限制链长度:避免链过长导致性能问题
- 使用弱引用:如果可能存在循环,使用弱引用打破循环
- 提供快速失败机制:当确定无法处理时,快速返回
- 日志记录:在每个节点记录日志,便于调试