框架中常用的过滤器、拦截器是如何实现的?

职责链模式常用在框架的开发中,为框架提供扩展点,让框架的使用者在不修改框架源码的情况下,基于扩展点添加新的功能。实际上,更具体点来说,职责链模式最常用来开发框架的过滤器和拦截器。

职责链模式

职责链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求为止。这种模式的主要目的是解耦请求的发送者和接收者,使得多个对象都有机会处理请求,而不需要事先指定具体的处理者。

原理

  1. 定义处理者接口:定义一个处理者接口,所有具体的处理者类都实现这个接口。
  2. 构建处理者链:每个处理者对象都有一个对下一个处理者的引用,形成一条处理者链。
  3. 传递请求:请求从链的起点开始传递,每个处理者决定是否处理请求以及是否将请求传递给下一个处理者。

设计意图

职责链模式的设计意图是:

  • 解耦请求的发送者和接收者:发送者不需要知道具体的接收者是谁,只需要将请求发送到链的起点即可。
  • 动态指定一组处理对象:可以在运行时动态地添加或删除处理者,调整处理链的顺序。
  • 允许多个对象处理请求:多个处理者可以协同工作,每个处理者只负责处理自己能够处理的部分请求。

实现步骤

  1. 定义处理者接口:定义一个处理者接口,声明处理请求的方法。
  2. 实现具体的处理者类:每个具体的处理者类实现处理者接口,并可以持有对下一个处理者的引用。
  3. 构建处理者链:将具体的处理者对象连接起来,形成一条处理者链。
  4. 发送请求:从链的起点开始传递请求,每个处理者决定是否处理请求以及是否将请求传递给下一个处理者。

示例代码

以下是一个用 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); // 无法处理,输出默认信息
}

代码解释

  1. Handler 抽象类 :定义了一个处理者接口,包含一个 setNext 方法用于设置下一个处理者,以及一个 handleRequest 方法用于处理请求。
  2. ConcreteHandler1ConcreteHandler2ConcreteHandler3 :分别实现了 Handler 接口,每个类负责处理特定类型的请求,并将无法处理的请求传递给下一个处理者。
  3. Request:表示请求,包含请求类型和内容。
  4. 构建处理者链 :通过 setNext 方法将处理者对象连接起来,形成一条处理者链。
  5. 发送请求:从链的起点开始传递请求,每个处理者决定是否处理请求以及是否将请求传递给下一个处理者。

常见应用场景

  1. HTTP 请求拦截器:在 HTTP 客户端中,可以在请求发送前和响应接收后添加多个拦截器,用于处理认证、日志记录、错误处理等。
  2. 日志过滤器:在日志系统中,可以添加多个过滤器,每个过滤器负责处理特定类型的日志记录。
  3. 权限拦截器:在权限管理系统中,可以添加多个拦截器,每个拦截器负责处理特定的权限验证。
  4. 事件处理器:在事件驱动系统中,可以添加多个处理器,每个处理器负责处理特定类型的事件。

示例代码

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)")
        }
    }
}

代码解释

  1. 定义拦截器协议

    • Interceptor 协议定义了一个 nextInterceptor 属性和一个 intercept 方法,用于处理请求。
  2. 定义请求类

    • HttpRequest 结构体表示 HTTP 请求,包含 URL、头部信息和请求体。
  3. 实现具体的拦截器类

    • LoggingInterceptor:记录请求日志。
    • AuthenticationInterceptor:添加认证头部信息。
    • ErrorHandlingInterceptor:处理请求过程中发生的错误。
  4. 构建拦截器链并发送请求

    • HttpClient 类用于管理拦截器链,并提供一个 sendRequest 方法来发送请求。
    • addInterceptor 方法用于添加拦截器到链中。
    • sendRequest 方法遍历拦截器链,逐个调用 intercept 方法处理请求。
  5. 使用示例

    • 创建 HttpClient 实例并添加拦截器。
    • 创建请求并调用 sendRequest 方法发送请求,处理响应或错误。

总结

通过职责链模式,框架可以提供灵活的扩展点,使得开发者可以在不修改框架源码的情况下,添加新的功能。这种模式特别适合用于实现过滤器和拦截器,因为它允许请求和响应在多个处理者之间传递,每个处理者负责处理特定的任务。这种设计使得系统更加模块化和可维护,同时也更容易扩展和修改。

相关推荐
阿笑带你学前端3 小时前
Flutter本地通知系统:记账提醒的深度实现
前端·flutter
用户093 小时前
如何避免写垃圾代码:iOS开发篇
ios·swiftui·swift
vker3 小时前
第 1 天:单例模式(Singleton Pattern)—— 创建型模式
java·设计模式
HarderCoder17 小时前
iOS 知识积累第一弹:从 struct 到 APP 生命周期的全景复盘
ios
孤鸿玉21 小时前
Fluter InteractiveViewer 与ScrollView滑动冲突问题解决
flutter
晨米酱1 天前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机1 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——性能模式
python·设计模式·架构