一搜网上讲责任链的写法都感觉好复杂我用简单实现让你秒懂并马上用到项目里前言搜了一圈责任链模式的文章要么搬出 UML 类图画半天要么搞一堆Handler、HandlerChain、AbstractHandler层层嵌套看得人头大。今天分享一个我在实际项目中用的责任链实现总共就 3 个核心文件代码不超过 80 行看完直接就能抄到你的项目里。一、先说场景什么时候需要责任链当你发现代码里有这种结构时if(条件A){// 处理逻辑 A}elseif(条件B){// 处理逻辑 B}elseif(条件C){// 处理逻辑 C}else{// 默认处理}每加一个场景就要改这个if-else越写越长越改越乱。责任链就是把这个 if-else 拆成一个个独立的处理节点串起来依次执行。二、核心就 3 个东西角色作用对应文件接口定义干什么和下一个是谁ILogicChain抽象类帮你管好下一个的引用AbstractLogicChain实现类每个节点的具体逻辑ReBrushChain/ContextCacheChain/DefaultChain三、代码逐行拆解1. 接口 — 定义链的契约publicinterfaceILogicChain{// 核心方法处理业务逻辑ListShardingContextlogic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa);// 获取下一个节点ILogicChainnext();// 追加下一个节点返回被追加的节点方便链式调用ILogicChainappendNext(ILogicChainnext);}关键点appendNext返回的是ILogicChain而不是void这样工厂里可以current current.appendNext(next)一路串下去。2. 抽象类 — 统一管理 next 引用Slf4jpublicabstractclassAbstractLogicChainimplementsILogicChain{privateILogicChainnext;OverridepublicILogicChainnext(){returnnext;}OverridepublicILogicChainappendNext(ILogicChainnext){this.nextnext;returnnext;// 返回下一个方便链式组装}// 子类可以标识自己的规则名protectedabstractStringrule();}就这么简单。next 的存取全在抽象类里子类完全不用关心链的维护。3. 实现类 — 每个节点只管自己的事节点 1反刷链优先级最高Order(1)publicclassReBrushChainextendsAbstractLogicChain{OverrideprotectedStringrule(){returnrebrush;}OverridepublicListShardingContextlogic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa){// 命中我的场景 → 我处理直接返回if(meta.reBrush()){// ... 构建并返回 brushContextListreturnbrushContextList;}// 不命中 → 交给下一个returnnext().logic(type,filter,meta);}}节点 2上下文缓存链Order(2)publicclassContextCacheChainextendsAbstractLogicChain{OverrideprotectedStringrule(){returncontext_cache;}OverridepublicListShardingContextlogic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa){ObjectcontextCacheValuefilter.getValue(CustomProperties.INTEGRATION_BATCH_SCOPE);// 命中 → 从缓存取 Scope直接返回if(null!contextCacheValue){// ... 构建并返回 contextListreturncontextList;}// 不命中 → 交给下一个returnnext().logic(type,filter,meta);}}节点 3默认链兜底Order(3)publicclassDefaultChainextendsAbstractLogicChain{OverrideprotectedStringrule(){returndefault;}OverridepublicListShardingContextlogic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa){// 兜底节点直接查数据库拿 ScopeListProcessDataScopescopeListdb.get();returnscopeList;}}注意DefaultChain 没有调用next()因为它是最后一个节点。4. 工厂 — 把链组装起来publicclassScopeChainFactory{privatestaticfinalMapString,ILogicChainCHAIN_GROUPnewHashMap();static{CHAIN_GROUP.put(rebrush,newReBrushChain());CHAIN_GROUP.put(context_cache,newContextCacheChain());CHAIN_GROUP.put(default,newDefaultChain());}// 定义执行顺序privatestaticfinalString[]SCOPE_MODELSnewString[]{rebrush,context_cache};publicstaticILogicChainopenChain(){// 拿到头节点ILogicChainlogicChainCHAIN_GROUP.get(SCOPE_MODELS[0]);ILogicChaincurrentlogicChain;// 依次串起来for(inti1;iSCOPE_MODELS.length;i){ILogicChainnextChainCHAIN_GROUP.get(SCOPE_MODELS[i]);currentcurrent.appendNext(nextChain);}// default 兜底确保链不会断current.appendNext(CHAIN_GROUP.get(default));returnlogicChain;}}四、调用方怎么用一行代码ListShardingContextresultScopeChainFactory.openChain().logic(salesType,filter,metaInfo);调用方完全不用关心内部走了哪个节点链会自己判断。五、执行流程图调用入口 ↓ ReBrushChain (Order1) ├─ 命中反刷场景 → 处理并返回 └─ 没命中 → next() ↓ ContextCacheChain (Order2) ├─ 有上下文缓存 → 处理并返回 └─ 没有缓存 → next() ↓ DefaultChain (Order3, 兜底) └─ 查数据库拿 Scope → 处理并返回六、和网上的写法比简单在哪对比项网上的写法本文写法类的数量5-8 个Handler、Chain、Builder、Context…3 个接口、抽象类、实现类组装方式Builder 嵌套 / Spring 注入 List 再排序静态 Map 数组定义顺序传递方式封装一个 Context 对象层层传递方法参数直接传清晰明了终止条件各种 boolean 返回值判断命中就 return没命中就next()七、要加新节点怎么办3 步新建实现类继承AbstractLogicChain实现logic()方法在ScopeChainFactory的CHAIN_GROUP里注册在SCOPE_MODELS数组里加上它的位置完事。不用改任何已有代码符合开闭原则。总结责任链模式的本质就是把 if-else 变成一串独立节点每个节点自己决定我处理还是交给下一个。不需要复杂的框架不需要一堆辅助类。一个接口、一个抽象类、几个实现类、一个工厂就够了。直接抄到你的项目里把logic()方法的参数换成你自己的业务参数马上就能用。
设计模式 之 责任链模式
一搜网上讲责任链的写法都感觉好复杂我用简单实现让你秒懂并马上用到项目里前言搜了一圈责任链模式的文章要么搬出 UML 类图画半天要么搞一堆Handler、HandlerChain、AbstractHandler层层嵌套看得人头大。今天分享一个我在实际项目中用的责任链实现总共就 3 个核心文件代码不超过 80 行看完直接就能抄到你的项目里。一、先说场景什么时候需要责任链当你发现代码里有这种结构时if(条件A){// 处理逻辑 A}elseif(条件B){// 处理逻辑 B}elseif(条件C){// 处理逻辑 C}else{// 默认处理}每加一个场景就要改这个if-else越写越长越改越乱。责任链就是把这个 if-else 拆成一个个独立的处理节点串起来依次执行。二、核心就 3 个东西角色作用对应文件接口定义干什么和下一个是谁ILogicChain抽象类帮你管好下一个的引用AbstractLogicChain实现类每个节点的具体逻辑ReBrushChain/ContextCacheChain/DefaultChain三、代码逐行拆解1. 接口 — 定义链的契约publicinterfaceILogicChain{// 核心方法处理业务逻辑ListShardingContextlogic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa);// 获取下一个节点ILogicChainnext();// 追加下一个节点返回被追加的节点方便链式调用ILogicChainappendNext(ILogicChainnext);}关键点appendNext返回的是ILogicChain而不是void这样工厂里可以current current.appendNext(next)一路串下去。2. 抽象类 — 统一管理 next 引用Slf4jpublicabstractclassAbstractLogicChainimplementsILogicChain{privateILogicChainnext;OverridepublicILogicChainnext(){returnnext;}OverridepublicILogicChainappendNext(ILogicChainnext){this.nextnext;returnnext;// 返回下一个方便链式组装}// 子类可以标识自己的规则名protectedabstractStringrule();}就这么简单。next 的存取全在抽象类里子类完全不用关心链的维护。3. 实现类 — 每个节点只管自己的事节点 1反刷链优先级最高Order(1)publicclassReBrushChainextendsAbstractLogicChain{OverrideprotectedStringrule(){returnrebrush;}OverridepublicListShardingContextlogic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa){// 命中我的场景 → 我处理直接返回if(meta.reBrush()){// ... 构建并返回 brushContextListreturnbrushContextList;}// 不命中 → 交给下一个returnnext().logic(type,filter,meta);}}节点 2上下文缓存链Order(2)publicclassContextCacheChainextendsAbstractLogicChain{OverrideprotectedStringrule(){returncontext_cache;}OverridepublicListShardingContextlogic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa){ObjectcontextCacheValuefilter.getValue(CustomProperties.INTEGRATION_BATCH_SCOPE);// 命中 → 从缓存取 Scope直接返回if(null!contextCacheValue){// ... 构建并返回 contextListreturncontextList;}// 不命中 → 交给下一个returnnext().logic(type,filter,meta);}}节点 3默认链兜底Order(3)publicclassDefaultChainextendsAbstractLogicChain{OverrideprotectedStringrule(){returndefault;}OverridepublicListShardingContextlogic(SalesOrderEnumtype,MageFilterfilter,MetaInfometa){// 兜底节点直接查数据库拿 ScopeListProcessDataScopescopeListdb.get();returnscopeList;}}注意DefaultChain 没有调用next()因为它是最后一个节点。4. 工厂 — 把链组装起来publicclassScopeChainFactory{privatestaticfinalMapString,ILogicChainCHAIN_GROUPnewHashMap();static{CHAIN_GROUP.put(rebrush,newReBrushChain());CHAIN_GROUP.put(context_cache,newContextCacheChain());CHAIN_GROUP.put(default,newDefaultChain());}// 定义执行顺序privatestaticfinalString[]SCOPE_MODELSnewString[]{rebrush,context_cache};publicstaticILogicChainopenChain(){// 拿到头节点ILogicChainlogicChainCHAIN_GROUP.get(SCOPE_MODELS[0]);ILogicChaincurrentlogicChain;// 依次串起来for(inti1;iSCOPE_MODELS.length;i){ILogicChainnextChainCHAIN_GROUP.get(SCOPE_MODELS[i]);currentcurrent.appendNext(nextChain);}// default 兜底确保链不会断current.appendNext(CHAIN_GROUP.get(default));returnlogicChain;}}四、调用方怎么用一行代码ListShardingContextresultScopeChainFactory.openChain().logic(salesType,filter,metaInfo);调用方完全不用关心内部走了哪个节点链会自己判断。五、执行流程图调用入口 ↓ ReBrushChain (Order1) ├─ 命中反刷场景 → 处理并返回 └─ 没命中 → next() ↓ ContextCacheChain (Order2) ├─ 有上下文缓存 → 处理并返回 └─ 没有缓存 → next() ↓ DefaultChain (Order3, 兜底) └─ 查数据库拿 Scope → 处理并返回六、和网上的写法比简单在哪对比项网上的写法本文写法类的数量5-8 个Handler、Chain、Builder、Context…3 个接口、抽象类、实现类组装方式Builder 嵌套 / Spring 注入 List 再排序静态 Map 数组定义顺序传递方式封装一个 Context 对象层层传递方法参数直接传清晰明了终止条件各种 boolean 返回值判断命中就 return没命中就next()七、要加新节点怎么办3 步新建实现类继承AbstractLogicChain实现logic()方法在ScopeChainFactory的CHAIN_GROUP里注册在SCOPE_MODELS数组里加上它的位置完事。不用改任何已有代码符合开闭原则。总结责任链模式的本质就是把 if-else 变成一串独立节点每个节点自己决定我处理还是交给下一个。不需要复杂的框架不需要一堆辅助类。一个接口、一个抽象类、几个实现类、一个工厂就够了。直接抄到你的项目里把logic()方法的参数换成你自己的业务参数马上就能用。