职责链模式常用在框架的开发中,为框架提供扩展点,让框架的使用者在不修改框架源码的情况下,基于扩展点添加新的功能。实际上,更具体点来说,职责链模式最常用来开发框架的过滤器和拦截器。
职责链模式
职责链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求为止。这种模式的主要目的是解耦请求的发送者和接收者,使得多个对象都有机会处理请求,而不需要事先指定具体的处理者。
原理
- 定义处理者接口:定义一个处理者接口,所有具体的处理者类都实现这个接口。
- 构建处理者链:每个处理者对象都有一个对下一个处理者的引用,形成一条处理者链。
- 传递请求:请求从链的起点开始传递,每个处理者决定是否处理请求以及是否将请求传递给下一个处理者。
设计意图
职责链模式的设计意图是:
- 解耦请求的发送者和接收者:发送者不需要知道具体的接收者是谁,只需要将请求发送到链的起点即可。
- 动态指定一组处理对象:可以在运行时动态地添加或删除处理者,调整处理链的顺序。
- 允许多个对象处理请求:多个处理者可以协同工作,每个处理者只负责处理自己能够处理的部分请求。
实现步骤
- 定义处理者接口:定义一个处理者接口,声明处理请求的方法。
- 实现具体的处理者类:每个具体的处理者类实现处理者接口,并可以持有对下一个处理者的引用。
- 构建处理者链:将具体的处理者对象连接起来,形成一条处理者链。
- 发送请求:从链的起点开始传递请求,每个处理者决定是否处理请求以及是否将请求传递给下一个处理者。
示例代码
以下是一个用 Dart 实现的职责链模式示例:
dart
// 定义处理者接口
abstract class Handler {
Handler? nextHandler;
void setNext(Handler handler) {
nextHandler = handler;
}
void handleRequest(Request request);
}
// 请求类
class Request {
final String type;
final String content;
Request({required this.type, required this.content});
}
// 具体处理者类1
class ConcreteHandler1 extends Handler {
@override
void handleRequest(Request request) {
if (request.type == 'Type1') {
print('ConcreteHandler1 handles ${request.type}: ${request.content}');
} else if (nextHandler != null) {
nextHandler!.handleRequest(request);
}
}
}
// 具体处理者类2
class ConcreteHandler2 extends Handler {
@override
void handleRequest(Request request) {
if (request.type == 'Type2') {
print('ConcreteHandler2 handles ${request.type}: ${request.content}');
} else if (nextHandler != null) {
nextHandler!.handleRequest(request);
}
}
}
// 具体处理者类3
class ConcreteHandler3 extends Handler {
@override
void handleRequest(Request request) {
if (request.type == 'Type3') {
print('ConcreteHandler3 handles ${request.type}: ${request.content}');
} else if (nextHandler != null) {
nextHandler!.handleRequest(request);
}
}
}
void main() {
// 创建具体的处理者对象
var handler1 = ConcreteHandler1();
var handler2 = ConcreteHandler2();
var handler3 = ConcreteHandler3();
// 构建处理者链
handler1.setNext(handler2);
handler2.setNext(handler3);
// 创建请求
var request1 = Request(type: 'Type1', content: 'Request 1');
var request2 = Request(type: 'Type2', content: 'Request 2');
var request3 = Request(type: 'Type3', content: 'Request 3');
var request4 = Request(type: 'Type4', content: 'Request 4');
// 发送请求
handler1.handleRequest(request1); // 处理 Type1 请求
handler1.handleRequest(request2); // 处理 Type2 请求
handler1.handleRequest(request3); // 处理 Type3 请求
handler1.handleRequest(request4); // 无法处理,输出默认信息
}
代码解释
Handler
抽象类 :定义了一个处理者接口,包含一个setNext
方法用于设置下一个处理者,以及一个handleRequest
方法用于处理请求。ConcreteHandler1
、ConcreteHandler2
和ConcreteHandler3
类 :分别实现了Handler
接口,每个类负责处理特定类型的请求,并将无法处理的请求传递给下一个处理者。Request
类:表示请求,包含请求类型和内容。- 构建处理者链 :通过
setNext
方法将处理者对象连接起来,形成一条处理者链。 - 发送请求:从链的起点开始传递请求,每个处理者决定是否处理请求以及是否将请求传递给下一个处理者。
常见应用场景
- HTTP 请求拦截器:在 HTTP 客户端中,可以在请求发送前和响应接收后添加多个拦截器,用于处理认证、日志记录、错误处理等。
- 日志过滤器:在日志系统中,可以添加多个过滤器,每个过滤器负责处理特定类型的日志记录。
- 权限拦截器:在权限管理系统中,可以添加多个拦截器,每个拦截器负责处理特定的权限验证。
- 事件处理器:在事件驱动系统中,可以添加多个处理器,每个处理器负责处理特定类型的事件。
示例代码
1. 定义拦截器协议
swift
protocol Interceptor {
var nextInterceptor: Interceptor? { get set }
func intercept(_ request: inout URLRequest)
}
2. 定义请求类
swift
struct HttpRequest {
let url: URL
var headers: [String: String]
var body: Data?
init(url: URL, headers: [String: String] = [:], body: Data? = nil) {
self.url = url
self.headers = headers
self.body = body
}
}
3. 实现具体的拦截器类
swift
class LoggingInterceptor: Interceptor {
var nextInterceptor: Interceptor?
func intercept(_ request: inout URLRequest) {
print("LoggingInterceptor: Request to \(request.url?.absoluteString ?? "")")
nextInterceptor?.intercept(&request)
}
}
class AuthenticationInterceptor: Interceptor {
var nextInterceptor: Interceptor?
func intercept(_ request: inout URLRequest) {
request.addValue("Bearer your-token", forHTTPHeaderField: "Authorization")
print("AuthenticationInterceptor: Added Authorization header")
nextInterceptor?.intercept(&request)
}
}
class ErrorHandlingInterceptor: Interceptor {
var nextInterceptor: Interceptor?
func intercept(_ request: inout URLRequest) {
do {
try nextInterceptor?.intercept(&request)
} catch {
print("ErrorHandlingInterceptor: Error occurred: \(error)")
}
}
}
4. 构建拦截器链并发送请求
swift
import Foundation
class HttpClient {
private var headInterceptor: Interceptor?
func addInterceptor(_ interceptor: Interceptor) {
if headInterceptor == nil {
headInterceptor = interceptor
} else {
var current = headInterceptor!
while current.nextInterceptor != nil {
current = current.nextInterceptor!
}
current.nextInterceptor = interceptor
}
}
func sendRequest(_ request: HttpRequest) async throws -> Data {
var urlRequest = URLRequest(url: request.url)
urlRequest.httpMethod = "POST"
urlRequest.allHTTPHeaderFields = request.headers
urlRequest.httpBody = request.body
var current = headInterceptor
while let interceptor = current {
interceptor.intercept(&urlRequest)
current = interceptor.nextInterceptor
}
let (data, _) = try await URLSession.shared.data(for: urlRequest)
return data
}
}
5. 使用示例
在应用中使用 HttpClient
并添加自定义拦截器。
swift
import Foundation
@main
struct App {
static func main() async {
// 创建 HttpClient 实例
let client = HttpClient()
// 添加拦截器
client.addInterceptor(LoggingInterceptor())
client.addInterceptor(AuthenticationInterceptor())
client.addInterceptor(ErrorHandlingInterceptor())
// 创建请求
let url = URL(string: "https://api.example.com/data")!
let headers: [String: String] = ["Content-Type": "application/json"]
let body = try? JSONSerialization.data(withJSONObject: ["key": "value"], options: [])
let request = HttpRequest(url: url, headers: headers, body: body)
// 发送请求
do {
let response = try await client.sendRequest(request)
print("Response data: \(response)")
} catch {
print("Request failed: \(error)")
}
}
}
代码解释
-
定义拦截器协议:
Interceptor
协议定义了一个nextInterceptor
属性和一个intercept
方法,用于处理请求。
-
定义请求类:
HttpRequest
结构体表示 HTTP 请求,包含 URL、头部信息和请求体。
-
实现具体的拦截器类:
LoggingInterceptor
:记录请求日志。AuthenticationInterceptor
:添加认证头部信息。ErrorHandlingInterceptor
:处理请求过程中发生的错误。
-
构建拦截器链并发送请求:
HttpClient
类用于管理拦截器链,并提供一个sendRequest
方法来发送请求。addInterceptor
方法用于添加拦截器到链中。sendRequest
方法遍历拦截器链,逐个调用intercept
方法处理请求。
-
使用示例:
- 创建
HttpClient
实例并添加拦截器。 - 创建请求并调用
sendRequest
方法发送请求,处理响应或错误。
- 创建
总结
通过职责链模式,框架可以提供灵活的扩展点,使得开发者可以在不修改框架源码的情况下,添加新的功能。这种模式特别适合用于实现过滤器和拦截器,因为它允许请求和响应在多个处理者之间传递,每个处理者负责处理特定的任务。这种设计使得系统更加模块化和可维护,同时也更容易扩展和修改。