跳转到内容

责任链模式

责任链设计模式使用方式,分为单例链、多例链模式,适合于多种节点间的复杂分支流转。

单例模式

  1. 定义装配链接口,提供添加节点和获取节点的方法

    /**
    * @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);
    }
  2. 编写抽象具体每个单链节点的业务逻辑处理方法

    /**
    * @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;
    }
  3. 封装添加加点和执行节点方法,后续节点都基于此抽象类来实现各种业务

    /**
    * @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 下一个节点
    */
    @Override
    public ILogicLink<T,D,R> next(){
    return next;
    }
    /**
    * 添加下一个责任链节点
    * @param next 下一个节点
    * @return 当前节点
    */
    @Override
    public 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);
    }
    }
  4. 编写单链测试类

    编写测试节点1,继承抽象类AbstractLogicLink,实现next方法。

    /**
    * @description 单链测试节点类1
    * @date 2025/3/13 22:44
    */
    @Service
    @Slf4j
    public class RuleLogic101 extends AbstractLogicLink<String, DynamicContext, String> {
    @Override
    public 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
    @Slf4j
    public class RuleLogic102 extends AbstractLogicLink<String, DynamicContext, String> {
    @Override
    public 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
    @Slf4j
    public class Rule01TradeRuleFactory {
    @Resource
    private RuleLogic101 ruleLogic101;
    @Resource
    private RuleLogic102 ruleLogic102;
    public ILogicLink<String, DynamicContext, String> openLogicLink(){
    ruleLogic101.appendNext(ruleLogic102);
    return ruleLogic101;
    }
    }
    编写单元测试类,验证业务执行流程
    ```java
    @SpringBootTest
    @RunWith(SpringRunner.class)
    @Slf4j
    public class Link01Test {
    @Resource
    public Rule01TradeRuleFactory rule01TradeRuleFactory;
    /**
    * 测试责任链单链模式
    * @throws Exception 抛出异常信息
    */
    @Test
    public void test_model01_01() throws Exception {
    ILogicLink<String, DynamicContext, String> logicLink = rule01TradeRuleFactory.openLogicLink();
    String result = logicLink.apply("单链测试", new DynamicContext());
    log.info("测试结果:{}", JSON.toJSONString(result));
    }
    }

    执行结果如下:

    image-20220409195204854

多例模式

多例链的设计要解耦链路和执行,下面是具体多例链的实现设计方式

  1. 编写设计链表接口

    /**
    * @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();
    }
  2. 链表接口的实现

    /**
    * @description 链表实现类
    * @date 2025/3/11 22:25
    */
    public class LinkedList<E> implements ILink<E> {
    private static final Logger log = LoggerFactory.getLogger(LinkedList.class);
    /**
    * 责任链名称
    */
    @Getter
    private final String name;
    @Getter
    transient 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;
    else
    f.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;
    else
    l.next = newNode;
    size++;
    }
    @Override
    public boolean add(E e) {
    linkLast(e);
    return true;
    }
    @Override
    public boolean addFirst(E e) {
    linkFirst(e);
    return true;
    }
    @Override
    public boolean addLast(E e) {
    linkLast(e);
    return true;
    }
    @Override
    public 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--;
    }
    @Override
    public 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;
    }
    }
    @Override
    public 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;
    }
    }
    }
  3. 封装抽象实现业务链路,

    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);
    }
    @Override
    public 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;
    }
    }
  4. 进行链路多例链表的链路装配

    **
    * @description 链路装配
    * @date 2025/3/13 22:33
    */
    public class LinkArmory<T,D,R>{
    private final BusinessLinkedList<T,D,R> logicLink;
    @SafeVarargs
    public 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;
    }
    }
  5. 编写多例链的测试

    前置动态上下文类和返回结果类

    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    @Data
    public 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
    @Service
    public class RuleLogic201 implements ILogicHandler<String, DynamicContext, XxxResponse> {
    @Override
    public XxxResponse apply(String requestParameter, DynamicContext dynamicContext) throws Exception {
    log.info("link model02 RuleLogic201");
    return next(requestParameter,dynamicContext);
    }
    }

    多例链业务流程节点2

    @Service
    @Slf4j
    public class RuleLogic202 implements ILogicHandler<String, DynamicContext, XxxResponse> {
    @Override
    public XxxResponse apply(String requestParameter, DynamicContext dynamicContext) throws Exception {
    log.info("link model02 RuleLogic202");
    return new XxxResponse("link model2多例模式");
    }
    }

    配置多例链节点流转工厂

    @Service
    @Slf4j
    public 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;
    @Test
    public void test_model02_01() throws Exception {
    XxxResponse apply = businessLinkedList01.apply("多例链1", new DynamicContext());
    log.info("测试结果:{}", JSON.toJSONString(apply));
    }
    @Test
    public void test_model02_02() throws Exception {
    XxxResponse apply = businessLinkedList02.apply("多例链2", new DynamicContext());
    log.info("测试结果;{}", JSON.toJSONString(apply));
    }
    }

    test_model02_01执行结果如下:

    test_model02_02执行结果如下: