23种计划模式-举动型模式-责任链

[复制链接]
发表于 2025-4-4 10:00:32 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
简介

责任链是一种举动计划模式,答应你把请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其转达给链上的下个处理者。
问题

假如你正在开辟一个订单体系。 你希望限定体系访问,只答应认证用户创建订单。 而管理员拥有全部订单的完全访问权限。
按照一样寻常的开辟思绪,你会依次执行这些查抄。 只要接收到包含用户根据的请求,体系就可以实行认证。 假如认证失败, 那就没有须要再进行后续查抄了。如下图。

接着,关于认证查抄的需求越来越多。比如为了不让原始数据直接转达到订单体系,需要在认证之后清理请求中的数据;比如为了对暴力密码破解或者爬虫请求进行限流,又需要在认证之后增加过滤来自同一 IP 地址的重复请求逻辑;比如为了进步体系响应速度,降低体系负载,又需要在请求发送给体系之前查抄有没有缓存结果,假如没有才会把请求发送给体系。如下图,这部分逻辑就会越来越多,越来越混乱。

而且,修改某个查抄步调大概也会影响其他的查抄步调。 尤其是当你希望复用这些查抄步调来掩护其他体系时,你只能复制部分代码, 因为这些体系只需要部分查抄步调。
解决

与许多其他举动计划模式一样, 责任链会把 特定举动转换成 叫做处理者的独立对象。 在上面示例里, 每个查抄步调都可以被抽取成仅有单个方法的类, 并执行查抄操纵。 请求和对应数据会被作为参数转达给这个方法。
这个模式发起你把这些处理者连成一条链。 链上的每个处理者都有一个成员变量来保存对于下一个处理者的引用。 除了处理请求外, 处理者还负责沿着链转达请求。 请求会在链上移动, 直到全部处理者都有机会对他进行处理。
更紧张的是: 处理者可以决定不再沿着链转达请求, 这就可以高效地取消全部后面的处理步调。
在我们的订单体系示例中, 处理者会在进行请求处理工作后决定要不要继续沿着链转达请求。 假如请求中包含正确的数据, 全部处理者都会执行本身的主要举动, 无论这个举动是身份验证还是数据缓存。

不过另有一种稍微不同的方式 (也是更经典一种), 那就是处理者接收到请求后本身决定是否能够对其进行处理。 假如本身能够处理, 处理者就不再继续转达请求。 因此在这种环境下, 每个请求要么最多有一个处理者进行处理, 要么没有任何处理者进行处理。 在处理图形用户界面元素栈中的变乱时, 这种方式非经常见。另外,其实很多计划模式都是从很早用Java写客户端界面引出的解决方案。
代码

  1. // Handler接口定义处理契约
  2. public interface Handler {
  3.     void handle(Request request) throws AuthException;
  4. }
  5. // BaseHandler实现链式传递逻辑
  6. public abstract class BaseHandler implements Handler {
  7.     private Handler next;
  8.     public BaseHandler setNext(Handler next) {
  9.         this.next = next;
  10.         return this;
  11.     }
  12.     protected void passToNext(Request request) throws AuthException {
  13.         if (next != null) next.handle(request);  // 核心链式调用逻辑
  14.     }
  15. }
  16. // 具体处理者1:用户认证
  17. class UserAuthHandler extends BaseHandler {
  18.     @Override
  19.     public void handle(Request request) throws AuthException {
  20.         if (!validateUser(request.getUserId())) {
  21.             throw new AuthException("用户未登录");
  22.         }
  23.         passToNext(request);  // 验证成功移交后续处理
  24.     }
  25. }
  26. // 具体处理者2:权限校验
  27. class PermissionHandler extends BaseHandler {
  28.     @Override
  29.     public void handle(Request request) throws AuthException {
  30.         if (!checkAdminPermission(request.getUserId())) {
  31.             throw new PermissionException("权限不足");
  32.         }
  33.         passToNext(request);
  34.     }
  35. }
  36. // Client动态组合处理链
  37. public class OrderService {
  38.     private Handler chain;
  39.     public OrderService() {
  40.         this.chain = new UserAuthHandler()
  41.             .setNext(new PermissionHandler());  // 灵活配置处理顺序
  42.     }
  43.     public void createOrder(Request request) {
  44.         chain.handle(request);  // 统一入口触发处理链
  45.         // 执行业务逻辑...
  46.     }
  47. }
复制代码
焦点改进点:


  • 解耦查抄逻辑:每个安全查抄独立成类,通过setNext组合链式结构
  • 动态扩展性:新增日记查抄仅需创建LogHandler并插入链中恣意位置
  • 复用性增强:在PaymentService中可重用UserAuthHandler而不需要重复验证代码
总结



  • (Handler)声明了全部具体处理者的通用接口。这个接口通常只包含单个方法,用于请求处理,但有时它还会包含一个设置链上 下一个处理者 的方法。
  • (Base Handler)是一个可选的类,你可以把全部处理者共用的样本代码放在里面。 通常环境下,这个类里界说了一个保存下个处理者引用的成员变量。客户端可以把下个处理者转达给上个处理者的构造函数或用setter方法 来创建链。这个类还可以实现默认的处理举动: 比如确定下个处理者存在后再把请求转达给它。
  • (Concrete Handlers)包含处理请求的实际代码。每 个处理者接收到请求后,都必须决定要不要处理,以及要不要沿 着链转达请求。 处理者通常是独立而且不可变的,需要通过构造函数一次性地获得 全部须要的数据。
  • (Client) 可根据程序逻辑一次性或者动态地生成链。 需要注意一下,请求可以发送给链上的恣意一个处理者,不一定是第一个处理者。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表