文章目录

  • 【设计模式】行为型模式:责任链模式


【设计模式】行为型模式:责任链模式

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

在工作中,遇到这么一个需求,有一个下单流程很复杂,其中某一个环节不通过,则直接返回失败,否则需要走完所有流程,例如下面几个步骤:

  • 1、判断用户是否已经登录
  • 2、判断用户是不是在系统黑名单
  • 3、判断下单参数是否完整,并检查格式
  • 4、判断收货地址是不是在配送范围内
  • 5、判断用户能否使用优惠卷
  • 最后,创建订单,保存订单,并发送短信给客户

我们就以这个流程为案例来分析责任链模式在实际生产中的应用

1、创建一个订单上下文

package com.example.chain;

import lombok.Data;

@Data
public class OrderContext {

    /**
     * 请求唯一序列ID
     */
    private String seqId;

    /**
     * 用户ID
     */
    private String userId;

    /**
     * 产品skuId
     */
    private Long skuId;

    /**
     * 下单数量
     */
    private Integer amount;

    /**
     * 用户收货地址ID
     */
    private String userAddressId;
}

2、创建抽象订单处理

package com.example.chain;

/**
 * 抽象订单处理
 */
public abstract class AbstractOrderHandle {

    /**
     * 责任链,下一个链接节点
     */
    private AbstractOrderHandle next;

    /**
     * 执行入口
     *
     * @param context
     * @return
     */
    public OrderContext execute(OrderContext context) {
        context = handle(context);
        // 判断是否还有下个责任链节点,没有的话,说明已经是最后一个节点
        if (getNext() != null) {
            getNext().execute(context);
        }
        return context;
    }

    /**
     * 对参数进行处理
     *
     * @param context
     * @return
     */
    public abstract OrderContext handle(OrderContext context);

    public AbstractOrderHandle getNext() {
        return next;
    }

    public void setNext(AbstractOrderHandle next) {
        this.next = next;
    }
}

3、编写处理流程的节点,我这里写了三个为例

package com.example.chain.handle;

import com.example.chain.AbstractOrderHandle;
import com.example.chain.OrderContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Order(1)
@Component
public class OneOrderHandle extends AbstractOrderHandle {

    @Override
    public OrderContext handle(OrderContext context) {
        System.out.println("责任链1");
        return context;
    }
}
package com.example.chain.handle;

import com.example.chain.AbstractOrderHandle;
import com.example.chain.OrderContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Order(2)
@Component
public class TwoOrderHandle extends AbstractOrderHandle {

    @Override
    public OrderContext handle(OrderContext context) {
        System.out.println("责任链2");
        return context;
    }
}
package com.example.chain.handle;

import com.example.chain.AbstractOrderHandle;
import com.example.chain.OrderContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Order(3)
@Component
public class ThreeOrderHandle extends AbstractOrderHandle {

    @Override
    public OrderContext handle(OrderContext context) {
        System.out.println("责任链3");
        return context;
    }
}

4、创建订单责任链管理

package com.example.chain;

import lombok.RequiredArgsConstructor;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.List;

/**
 * 订单责任链管理
 */
@Component
@RequiredArgsConstructor
public class OrderHandleManager {

    private final List<AbstractOrderHandle> orderHandleList;

    @PostConstruct
    public void init() {
        //如果List没有按照@Order注解方式排序,可以通过如下方式手动排序
        Collections.sort(orderHandleList, AnnotationAwareOrderComparator.INSTANCE);
        int size = orderHandleList.size();
        for (int i = 0; i < size; i++) {
            if (i == size - 1) {
                orderHandleList.get(i).setNext(null);
            } else {
                orderHandleList.get(i).setNext(orderHandleList.get(i + 1));
            }
        }
    }

    /**
     * 执行处理
     *
     * @param context
     * @return
     */
    public OrderContext execute(OrderContext context) {
        context = orderHandleList.get(0).execute(context);
        return context;
    }
}

5、 编写测试接口

package com.example.chain;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class TestController {

    private final OrderHandleManager orderHandleManager;

    @GetMapping("/test")
    public void test() {
        OrderContext context = orderHandleManager.execute(new OrderContext());
        System.out.println(context.toString());
    }
}

到此责任链模式就完成了