参考Netty源码实现优雅的责任链设计模式

8 篇文章 9 订阅
6 篇文章 1 订阅
本文深入探讨了如何基于Netty4.X的Pipeline实现责任链设计模式,强调了责任链在实际工程中的重要性和灵活性。通过定义事件、设计Context和Pipeline,以及展示业务逻辑代码的实现,阐述了如何优雅地构建和维护责任链。同时,文章提供了详细的代码示例以供参考,有助于开发者更好地理解和应用责任链模式。
摘要由CSDN通过智能技术生成

Netty优雅的责任链实现

如各位希望转载或引用,请注明出处,尊重原创,谢谢。如有疑问或错误,欢迎邮件沟通。

gitHub地址:https://github.com/thinkingfioa
邮箱地址:vlinyes@163.com
博客地址: https://blog.csdn.net/thinking_fioa
gitHub项目地址:https://github.com/thinkingfioa/tech-summary
gitHub项目代码地址:https://github.com/thinkingfioa/tech-summary-code

本文重点

本文重点介绍如何优雅的实现责任链设计模式,思路参考的是Netty4.X的Pipeline源码。

1. 背景

责任链模式是重点的设计模式,使用场景非常频繁,但市场上讲解责任链模式的代码都太简单或照搬基础实现,工程性太弱,参考意义不大。

本文主要参考Netty4.X中实现了Pipeline实现,提炼其精髓,方便各位开发者参考,可极大的方便代码维护与实现。

2. 分析

2.1 事件传递

一个责任链应该支持多个事件,每个事件都有链上不同的Handler或同一个Handler处理。

我们建议每个Handler功能单一,仅需实现自己关心的事件,其他事件一律交由后续其他Handler处理。

定义事件

public enum EventTypeEnum {
  EVENT, STOP;
}

根据其定义的事件,建立出上层抽象Handler

public interface IEventHandler {

  /**
   * 消息处理. {@link EventTypeEnum#EVENT}
   */
  void eventHandler(IEventContext ctx, Object msg) throws Exception;

  /**
   * 关闭. {@link EventTypeEnum#STOP}
   */
  void stop(IEventContext ctx) throws Exception;

  /**
   * 发生异常. 缺省提供,方便异常拦截
   */
  void exceptionCaught(IEventContext ctx, Throwable cause) throws Exception;
}

提醒:考虑到责任链中中的业务代码代码实现产生逻辑异常,我们缺省提供异常事件。

2.2 代码设计

2.2.1 Context设计

责任链通俗的说就是一个双向链表,设计Context负责串起来整个责任链,每个Context有三个重要的属性

  • prex Context ----- 指向前一个节点
  • next Context ----- 指向后一个节点
  • handler IEventhandler ----- 当前节点的业务处理逻辑

Context在设计过程中对用户来说是完全透明的,程序员仅需实现具体的业务逻辑handler,并将其加入到pipeline中,加入的过程会自动封装成Context对象添加到责任链中。

Context缺省有fireEventHandler(…)和invokeEventHandler(…)

  • fireEventHandler(…)方法 ----- 主动调用意味着将该事件传递给责任链下个节点处理
  • invokeEventHandler(…)方法 ----- 执行业务逻辑代码的Handler,无须主动调用,传递过程中会Context自动会调用
public class DefaultEventContext implements IEventContext {

  volatile DefaultEventContext prex;
  volatile DefaultEventContext next;

  private final IEventHandler handler;

  DefaultEventContext(IEventHandler handler) {
    this.handler = handler;
  }

  @Override
  public void fireEventHandler(Object event) throws Exception {
    next.invokeEventHandler(next, event);
  }

  @Override
  public void invokeEventHandler(IEventContext ctx, Object event) throws Exception {
    handler.eventHandler(ctx, event);
  }

  //... 省略
}
2.2.2 Pipeline设计

Pipeline对象中缺省会提供headCtx和tailCtx,分别是责任链的头和责任链的尾。用户自己实现的业务逻辑Handler处于二者中间。

Pipeline提供addLast(…)、addBefore(…)和remove(…)支持动态编排责任链,整个增强了责任链的灵活性,这个点对于责任链来说非常重要。

用户仅需创建一个Pipeline对象,然后将自己实现的业务逻辑Handler添加到Pipeline事件中即可,封装性和维护性都大大提高。

public class HandlerPipeline {

  private final DefaultEventContext headCtx;
  private final DefaultEventContext tailCtx;

  public HandlerPipeline(HeadHandler head, TailHandler tail) {
    headCtx = new DefaultEventContext(head);
    tailCtx = new DefaultEventContext(tail);
    headCtx.next = tailCtx;
    tailCtx.prex = headCtx;
  }

  /**
   * 在Pipeline的尾部添加节点.
   */
  public HandlerPipeline addLast(IEventHandler handler) {
    DefaultEventContext ctx = new DefaultEventContext(handler);
    DefaultEventContext prev = tailCtx.prex;
    ctx.prex = prev;
    ctx.next = tailCtx;
    prev.next = ctx;
    tailCtx.prex = ctx;
    return this;
  }

  public HandlerPipeline addBefore(IEventHandler handler) {
    // TODO 暂未实现
    return this;
  }

  public HandlerPipeline remove(IEventHandler handler) {
    // TODO 暂未实现
    return this;
  }

  /**
   * 传递event事件
   */
  public void fireEventHandler(Object event) throws Exception {
    headCtx.fireEventHandler(event);
  }
  // ...省略
}
2.2.3 业务逻辑代码实现

具体的业务逻辑代码可以根据具体场景实现,建议Handler尽量保证功能单一。如果不希望每个业务的Handler都实现所有的Handler,可以创建一个抽象的父类AbstractBizHandler,该父类缺省往后传递所有的事件

public abstract class AbstractBizHandler implements ICustomBizHandler {

  @Override
  public void eventHandler(IEventContext ctx, Object msg) throws Exception {
    // 向后传递事件
    ctx.fireEventHandler(msg);
  }

  @Override
  public void stop(IEventContext ctx) throws Exception {
    // 向后传递事件
    ctx.fireStop();
  }

  @Override
  public void exceptionCaught(IEventContext ctx, Throwable cause) throws Exception {
    // 异常向后传递
    ctx.fireExceptionCaught(cause);
  }
}

3. 详细代码实现

详细代码实现,请参考: tech-summary-code

参考资料

  • Netty源码中的Pipeline
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值