如各位希望转载或引用,请注明出处,尊重原创,谢谢。如有疑问或错误,欢迎邮件沟通。
gitHub地址:https://github.com/thinkingfioa
邮箱地址:[email protected]
博客地址: https://blog.csdn.net/thinking_fioa
gitHub项目地址:https://github.com/thinkingfioa/tech-summary
gitHub项目代码地址:https://github.com/thinkingfioa/tech-summary-code
本文重点介绍如何优雅的实现责任链设计模式,思路参考的是Netty4.X的Pipeline源码。
责任链模式是重点的设计模式,使用场景非常频繁,但市场上讲解责任链模式的代码都太简单或照搬基础实现,工程性太弱,参考意义不大。
本文主要参考Netty4.X中实现了Pipeline实现,提炼其精髓,方便各位开发者参考,可极大的方便代码维护与实现。
一个责任链应该支持多个事件,每个事件都有链上不同的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;
}
提醒:考虑到责任链中中的业务代码代码实现产生逻辑异常,我们缺省提供异常事件。
责任链通俗的说就是一个双向链表,设计Context负责串起来整个责任链,每个Context有三个重要的属性
Context在设计过程中对用户来说是完全透明的,程序员仅需实现具体的业务逻辑handler,并将其加入到pipeline中,加入的过程会自动封装成Context对象添加到责任链中。
Context缺省有fireEventHandler(…)和invokeEventHandler(…)
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);
}
//... 省略
}
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);
}
// ...省略
}
具体的业务逻辑代码可以根据具体场景实现,建议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);
}
}
详细代码实现,请参考: tech-summary-code