责任链模式
责任链设计模式使用方式,分为单例链、多例链模式,适合于多种节点间的复杂分支流转。
单例模式
-
定义装配链接口,提供添加节点和获取节点的方法
/*** @description 装配链* @date 2025/3/10 22:35*/public interface ILogicChainArmory<T,D,R>{/*** 获取下一个责任链节点* @return 下一个节点*/ILogicLink<T,D,R> next();/*** 添加下一个责任链节点* @param next 下一个节点* @return 当前节点*/ILogicLink<T,D,R> appendNext(ILogicLink<T,D,R> next);} -
编写抽象具体每个单链节点的业务逻辑处理方法
/*** @description 责任链* @date 2025/3/10 22:36*/public interface ILogicLink<T, D, R> extends ILogicChainArmory<T, D, R> {/*** 责任链业务逻辑受理方法** @param requestParameter 参数* @param dynamicContext 动态上下文* @return 业务处理结果* @throws Exception 异常*/R apply(T requestParameter, D dynamicContext) throws Exception;} -
封装添加加点和执行节点方法,后续节点都基于此抽象类来实现各种业务
/*** @description 责任链抽象类* @date 2025/3/10 22:40*/public abstract class AbstractLogicLink<T,D,R> implements ILogicLink<T,D,R>{private ILogicLink<T,D,R> next;/*** 获取下一个责任链节点* @return 下一个节点*/@Overridepublic ILogicLink<T,D,R> next(){return next;}/*** 添加下一个责任链节点* @param next 下一个节点* @return 当前节点*/@Overridepublic ILogicLink<T,D,R> appendNext(ILogicLink<T,D,R> next){this.next = next;return next;}protected R next(T requestParameter,D dynamicContext) throws Exception{return next.apply(requestParameter,dynamicContext);}} -
编写单链测试类
编写测试节点1,继承抽象类AbstractLogicLink,实现next方法。
/*** @description 单链测试节点类1* @date 2025/3/13 22:44*/@Service@Slf4jpublic class RuleLogic101 extends AbstractLogicLink<String, DynamicContext, String> {@Overridepublic String apply(String requestParameter, DynamicContext dynamicContext) throws Exception {log.info("link model01 RuleLogic101");return next(requestParameter, dynamicContext);}}编写测试节点2
/*** @description 单链测试2具体逻辑* @date 2025/3/13 23:44*/@Service@Slf4jpublic class RuleLogic102 extends AbstractLogicLink<String, DynamicContext, String> {@Overridepublic String apply(String requestParameter, DynamicContext dynamicContext) throws Exception {log.info("link model01 RuleLogic102");return "link model1 单链模式!";}}编写单链节点的工厂,通过Spring注入的方式编排具体节点的流转状态
/*** @description* @date 2025/3/13 22:42*/@Service@Slf4jpublic class Rule01TradeRuleFactory {@Resourceprivate RuleLogic101 ruleLogic101;@Resourceprivate RuleLogic102 ruleLogic102;public ILogicLink<String, DynamicContext, String> openLogicLink(){ruleLogic101.appendNext(ruleLogic102);return ruleLogic101;}}编写单元测试类,验证业务执行流程```java@SpringBootTest@RunWith(SpringRunner.class)@Slf4jpublic class Link01Test {@Resourcepublic Rule01TradeRuleFactory rule01TradeRuleFactory;/*** 测试责任链单链模式* @throws Exception 抛出异常信息*/@Testpublic void test_model01_01() throws Exception {ILogicLink<String, DynamicContext, String> logicLink = rule01TradeRuleFactory.openLogicLink();String result = logicLink.apply("单链测试", new DynamicContext());log.info("测试结果:{}", JSON.toJSONString(result));}}执行结果如下:
多例模式
多例链的设计要解耦链路和执行,下面是具体多例链的实现设计方式
-
编写设计链表接口
/*** @description 抽象链表接口方法* @date 2025/3/11 22:19*/public interface ILink<E> {/*** 添加元素** @param e 元素* @return true 成功 false 失败*/boolean add(E e);/*** 添元素加到链表头部** @param e 元素* @return true 成功 false 失败*/boolean addFirst(E e);/*** 添加元素到链表尾部** @param e 元素* @return true 成功 false 失败*/boolean addLast(E e);/*** 从链表中移除元素** @param e 元素* @return true 成功 false 失败*/boolean remove(E e);/*** 指定下标获取链表节点元素** @param index 下标* @return 元素*/E get(int index);/*** 打印链表*/void printLinkList();} -
链表接口的实现
/*** @description 链表实现类* @date 2025/3/11 22:25*/public class LinkedList<E> implements ILink<E> {private static final Logger log = LoggerFactory.getLogger(LinkedList.class);/*** 责任链名称*/@Getterprivate final String name;@Gettertransient int size = 0;/*** 头节点*/transient Node<E> first;/*** 尾节点*/transient Node<E> last;public LinkedList(String name) {this.name = name;}/*** 添加到节点头部** @param e 元素*/void linkFirst(E e) {final Node<E> f = first;final Node<E> newNode = new Node<>(null, e, f);first = newNode;if (f == null)// 链表的头节点为空last = newNode;elsef.prev = newNode;size++;}/*** 添加到节点尾部** @param e 元素*/void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)// 链表的尾节点为空first = newNode;elsel.next = newNode;size++;}@Overridepublic boolean add(E e) {linkLast(e);return true;}@Overridepublic boolean addFirst(E e) {linkFirst(e);return true;}@Overridepublic boolean addLast(E e) {linkLast(e);return true;}@Overridepublic boolean remove(Object o) {// 元素为空if (o == null) {for (Node<E> x = first; x != null; x = x.next) {if (x.item == null) {unlink(x);return true;}}} else {for (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item)) {unlink(x);return true;}}}return false;}/*** 链表断链方法** @param x 当前节点*/void unlink(Node<E> x) {final E element = x.item;final Node<E> next = x.next;final Node<E> prev = x.prev;// x的上一个节点为空if (prev == null) {first = next;} else {prev.next = next;x.prev = null;}// x的下一个节点为空if (next == null) {last = prev;} else {next.prev = prev;x.next = null;}x.item = null;size--;}@Overridepublic E get(int index) {return node(index).item;}Node<E> node(int index) {if (index < (size >> 1)) {Node<E> x = first;for (int i = 0; i < index; i++)x = x.next;return x;} else {Node<E> x = last;for (int i = size - 1; i > index; i--)x = x.prev;return x;}}@Overridepublic void printLinkList() {if (this.size == 0) {log.error("link is empty");} else {Node<E> temp = first;log.info("目前的列表,头节点:{},尾节点:{},整体:", first.item, last.item);while (temp != null) {log.info("{}", temp.item);temp = temp.next;}}}protected static class Node<E> {/*** 元素*/E item;/*** 下一个节点*/Node<E> next;/*** 上一个节点*/Node<E> prev;public Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}}} -
封装抽象实现业务链路,
public interface ILogicHandler<T,D,R>{default R next(T requestParameter,D dynamicContext){return null;}R apply(T requestParameter,D dynamicContext) throws Exception;}/*** @description 业务链路实现类* @date 2025/3/13 22:21*/public class BusinessLinkedList<T,D,R> extends LinkedList<ILogicHandler<T,D,R>> implements ILogicHandler<T,D,R> {public BusinessLinkedList(String name){super(name);}@Overridepublic R apply(T requestParameter, D dynamicContext) throws Exception {// 获取当前节点Node<ILogicHandler<T, D, R>> current = this.first;// 循环处理节点do{ILogicHandler<T, D, R> item = current.item;R apply = item.apply(requestParameter, dynamicContext);if (null != apply) return apply;// 执行下一个节点current = current.next;}while (null != current);return null;}} -
进行链路多例链表的链路装配
*** @description 链路装配* @date 2025/3/13 22:33*/public class LinkArmory<T,D,R>{private final BusinessLinkedList<T,D,R> logicLink;@SafeVarargspublic LinkArmory(String linkName, ILogicHandler<T,D,R>... logicHandlers) {logicLink = new BusinessLinkedList<>(linkName);for (ILogicHandler<T, D, R> logicHandler : logicHandlers) {logicLink.add(logicHandler);}}public BusinessLinkedList<T,D,R> getLogicLink() {return logicLink;}} -
编写多例链的测试
前置动态上下文类和返回结果类
@AllArgsConstructor@NoArgsConstructor@Builder@Datapublic class DynamicContext {private String args;}public class XxxResponse {private final String args;public XxxResponse(String args) {this.args = args;}public String getAge() {return args;}}多例链业务流程节点1
@Slf4j@Servicepublic class RuleLogic201 implements ILogicHandler<String, DynamicContext, XxxResponse> {@Overridepublic XxxResponse apply(String requestParameter, DynamicContext dynamicContext) throws Exception {log.info("link model02 RuleLogic201");return next(requestParameter,dynamicContext);}}多例链业务流程节点2
@Service@Slf4jpublic class RuleLogic202 implements ILogicHandler<String, DynamicContext, XxxResponse> {@Overridepublic XxxResponse apply(String requestParameter, DynamicContext dynamicContext) throws Exception {log.info("link model02 RuleLogic202");return new XxxResponse("link model2多例模式");}}配置多例链节点流转工厂
@Service@Slf4jpublic class Rule02TradeRuleFactory {@Bean("demo01")public BusinessLinkedList<String, DynamicContext, XxxResponse> demo01(RuleLogic201 ruleLogic201, RuleLogic202 ruleLogic202) {LinkArmory<String, DynamicContext, XxxResponse> linkArmory = new LinkArmory<>("demo01",ruleLogic201,ruleLogic202);return linkArmory.getLogicLink();}@Bean("demo02")public BusinessLinkedList<String,DynamicContext,XxxResponse> demo02(RuleLogic202 ruleLogic202) {LinkArmory<String, DynamicContext, XxxResponse> linkArmory = new LinkArmory<>("demo02", ruleLogic202);return linkArmory.getLogicLink();}}多例链单元测试节点
@Slf4j@SpringBootTest@RunWith(SpringRunner.class)public class Link02Test {@Resource(name = "demo01")private BusinessLinkedList<String, DynamicContext, XxxResponse> businessLinkedList01;@Resource(name = "demo02")private BusinessLinkedList<String,DynamicContext,XxxResponse> businessLinkedList02;@Testpublic void test_model02_01() throws Exception {XxxResponse apply = businessLinkedList01.apply("多例链1", new DynamicContext());log.info("测试结果:{}", JSON.toJSONString(apply));}@Testpublic void test_model02_02() throws Exception {XxxResponse apply = businessLinkedList02.apply("多例链2", new DynamicContext());log.info("测试结果;{}", JSON.toJSONString(apply));}}test_model02_01执行结果如下:
test_model02_02执行结果如下: