设计模式 之 责任链模式
2026/5/24 0:09:41 网站建设 项目流程

一搜网上讲责任链的写法都感觉好复杂?我用简单实现让你秒懂并马上用到项目里

前言

搜了一圈责任链模式的文章,要么搬出 UML 类图画半天,要么搞一堆HandlerHandlerChainAbstractHandler层层嵌套,看得人头大。

今天分享一个我在实际项目中用的责任链实现,总共就 3 个核心文件,代码不超过 80 行,看完直接就能抄到你的项目里。


一、先说场景:什么时候需要责任链?

当你发现代码里有这种结构时:

if(条件A){// 处理逻辑 A}elseif(条件B){// 处理逻辑 B}elseif(条件C){// 处理逻辑 C}else{// 默认处理}

每加一个场景就要改这个if-else,越写越长,越改越乱。

责任链就是把这个 if-else 拆成一个个独立的处理节点,串起来依次执行。


二、核心就 3 个东西

角色作用对应文件
接口定义"干什么"和"下一个是谁"ILogicChain
抽象类帮你管好"下一个"的引用AbstractLogicChain
实现类每个节点的具体逻辑ReBrushChain/ContextCacheChain/DefaultChain

三、代码逐行拆解

1. 接口 — 定义链的契约

publicinterfaceILogicChain{// 核心方法:处理业务逻辑List<ShardingContext>logic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa);// 获取下一个节点ILogicChainnext();// 追加下一个节点(返回被追加的节点,方便链式调用)ILogicChainappendNext(ILogicChainnext);}

关键点appendNext返回的是ILogicChain而不是void,这样工厂里可以current = current.appendNext(next)一路串下去。


2. 抽象类 — 统一管理 next 引用

@Slf4jpublicabstractclassAbstractLogicChainimplementsILogicChain{privateILogicChainnext;@OverridepublicILogicChainnext(){returnnext;}@OverridepublicILogicChainappendNext(ILogicChainnext){this.next=next;returnnext;// 返回下一个,方便链式组装}// 子类可以标识自己的规则名protectedabstractStringrule();}

就这么简单。next 的存取全在抽象类里,子类完全不用关心链的维护。


3. 实现类 — 每个节点只管自己的事

节点 1:反刷链(优先级最高)
@Order(1)publicclassReBrushChainextendsAbstractLogicChain{@OverrideprotectedStringrule(){return"rebrush";}@OverridepublicList<ShardingContext>logic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa){// 命中我的场景 → 我处理,直接返回if(meta.reBrush()){// ... 构建并返回 brushContextListreturnbrushContextList;}// 不命中 → 交给下一个returnnext().logic(type,filter,meta);}}
节点 2:上下文缓存链
@Order(2)publicclassContextCacheChainextendsAbstractLogicChain{@OverrideprotectedStringrule(){return"context_cache";}@OverridepublicList<ShardingContext>logic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa){ObjectcontextCacheValue=filter.getValue(CustomProperties.INTEGRATION_BATCH_SCOPE);// 命中 → 从缓存取 Scope,直接返回if(null!=contextCacheValue){// ... 构建并返回 contextListreturncontextList;}// 不命中 → 交给下一个returnnext().logic(type,filter,meta);}}
节点 3:默认链(兜底)
@Order(3)publicclassDefaultChainextendsAbstractLogicChain{@OverrideprotectedStringrule(){return"default";}@OverridepublicList<ShardingContext>logic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa){// 兜底节点:直接查数据库拿 ScopeList<ProcessDataScope>scopeList=db.get();returnscopeList;}}

注意:DefaultChain 没有调用next(),因为它是最后一个节点。


4. 工厂 — 把链组装起来

publicclassScopeChainFactory{privatestaticfinalMap<String,ILogicChain>CHAIN_GROUP=newHashMap<>();static{CHAIN_GROUP.put("rebrush",newReBrushChain());CHAIN_GROUP.put("context_cache",newContextCacheChain());CHAIN_GROUP.put("default",newDefaultChain());}// 定义执行顺序privatestaticfinalString[]SCOPE_MODELS=newString[]{"rebrush","context_cache"};publicstaticILogicChainopenChain(){// 拿到头节点ILogicChainlogicChain=CHAIN_GROUP.get(SCOPE_MODELS[0]);ILogicChaincurrent=logicChain;// 依次串起来for(inti=1;i<SCOPE_MODELS.length;i++){ILogicChainnextChain=CHAIN_GROUP.get(SCOPE_MODELS[i]);current=current.appendNext(nextChain);}// default 兜底,确保链不会断current.appendNext(CHAIN_GROUP.get("default"));returnlogicChain;}}

四、调用方怎么用?

一行代码:

List<ShardingContext>result=ScopeChainFactory.openChain().logic(salesType,filter,metaInfo);

调用方完全不用关心内部走了哪个节点,链会自己判断。


五、执行流程图

调用入口 ↓ ReBrushChain (Order=1) ├─ 命中反刷场景? → 处理并返回 └─ 没命中 → next() ↓ ContextCacheChain (Order=2) ├─ 有上下文缓存? → 处理并返回 └─ 没有缓存 → next() ↓ DefaultChain (Order=3, 兜底) └─ 查数据库拿 Scope → 处理并返回

六、和网上的写法比,简单在哪?

对比项网上的写法本文写法
类的数量5-8 个(Handler、Chain、Builder、Context…)3 个(接口、抽象类、实现类)
组装方式Builder 嵌套 / Spring 注入 List 再排序静态 Map + 数组定义顺序
传递方式封装一个 Context 对象层层传递方法参数直接传,清晰明了
终止条件各种 boolean 返回值判断命中就 return,没命中就next()

七、要加新节点怎么办?

3 步:

  1. 新建实现类,继承AbstractLogicChain,实现logic()方法
  2. ScopeChainFactoryCHAIN_GROUP里注册
  3. SCOPE_MODELS数组里加上它的位置

完事。不用改任何已有代码,符合开闭原则。


总结

责任链模式的本质就是:把 if-else 变成一串独立节点,每个节点自己决定"我处理"还是"交给下一个"。

不需要复杂的框架,不需要一堆辅助类。一个接口、一个抽象类、几个实现类、一个工厂,就够了。

直接抄到你的项目里,把logic()方法的参数换成你自己的业务参数,马上就能用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询