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

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

职责链模式

职责链模式(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 方法发送请求,处理响应或错误。

总结

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

相关推荐
思忖小下几秒前
梳理你的思路(从OOP到架构设计)_简介设计模式
设计模式·架构·eit
liyinuo20172 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
网安墨雨3 小时前
iOS应用网络安全之HTTPS
web安全·ios·https
aaasssdddd964 小时前
C++的封装(十四):《设计模式》这本书
数据结构·c++·设计模式
T1an-14 小时前
设计模式之【观察者模式】
观察者模式·设计模式
福大大架构师每日一题5 小时前
37.1 prometheus管理接口源码讲解
ios·iphone·prometheus
思忖小下6 小时前
梳理你的思路(从OOP到架构设计)_设计模式Factory Method模式
设计模式·工厂方法模式·eit
霁月风7 小时前
设计模式——工厂方法模式
c++·设计模式·工厂方法模式
发飙的蜗牛'9 小时前
23种设计模式
android·java·设计模式
NorthCastle19 小时前
设计模式-创建型模式-简单工厂模式详解
设计模式·简单工厂模式