责任链模式


设计模式 总目录

https://preparedata.blog.csdn.net/article/details/134512591


文章目录

    • 设计模式 总目录
    • 一、案例
    • 二、责任链
      • 2.1 责任链生成类
      • 2.2 链路节点执行器 (基类,需要被继承)
    • 三、订单业务 责任链 (案例一)
      • 3.1 订单链抽象类 (组装链路、自定义订单公共方法)
      • 3.2 链路节点-参数检查
      • 3.3 链路节点-优惠券核销
      • 3.4 链路节点-积分抵扣
      • 3.5 链路节点-订单消息通知
      • 3.6 链路节点-处理购物车
      • 3.7 链路节点-锁定库存
    • 四、审批业务 责任链 (案例二)
      • 4.1 审批链抽象类 (组装链路、自定义审批公共方法)
      • 4.2 链路节点-老板审批
      • 4.3 链路节点-经理审批
    • 五、代码结构
    • 六、调用


一、案例

个人理解责任链模式在于,将业务功能拆分成各节点(职责节点),再打包成有顺序性的链路。
如果节点处理成功,可进入下一节点 。以下示例代码未包含此逻辑,但可在基类中添加状态来实现,偷个懒,暂不实现了。

案例一:订单创建
订单创建,可能会包含参数检查、锁定库存、优惠券核销、积分抵扣、处理购物车、订单消息通知等逻辑
但不同的订单类型可能包含的节点不同或顺序。现在可以将订单创建逻辑拆分。

不同的订单类型 可以提现设置不同的执行链路来处理订单。
如后续需添加节点或删除节点。也能快速适配

案例一:审批
审批流程,可能会包含组长、经理、行政、老板等逻辑
但不同的审批业务可能包含的节点不同或顺序。现在可以将逻辑拆分。

不同的审批业务 可以提现设置不同的执行链路来处理。


二、责任链

2.1 责任链生成类

利用泛型 T 来约束子类中需继承ResponsibilityChainPathExecute

利用泛型 P 来泛型化处理节点执行的参数, 实际业务中,可以将订单创建、审批相差很大的业务使用上下文来处理节点执行的参数

链路节点执行使用了递归 invoke(ResponsibilityChainPathExecute nextChain, P p) ,所以在组装链路时,需要保证链路有始有终,不能循环依赖

package com.pd.shopping.order.designptern.chain;

/**
 * @author hl
 */
public class ResponsibilityChain<T extends ResponsibilityChainPathExecute, P> {

    /**
     * 责任链的开始节点
     */
    private T executeChain;

    /**
     * 构造函数
     * @param startChain 责任链的开始节点
     */
    public ResponsibilityChain(T startChain) {
        executeChain = startChain;
    }

    /**
     * 责任链的调用
     * @param p 执行方法的泛型参数
     */
    public void invoke(P p) {
        if(executeChain == null){
            return;
        }
        executeChain.execute(p);
        ResponsibilityChainPathExecute nextChain = executeChain.getNextChain();
        if(nextChain == null){
            return;
        }
        this.invoke(nextChain,p);
    }

    /**
     * 责任链后续节点执行 递归执行
     *
     * @param nextChain 责任链下一个节点
     * @param p 执行方法的泛型参数
     */
    private void invoke(ResponsibilityChainPathExecute nextChain, P p) {
        if(nextChain == null){
            return;
        }
        nextChain.execute(p);
        ResponsibilityChainPathExecute nextChain1 = nextChain.getNextChain();
        if(nextChain1 == null){
            return;
        }
        this.invoke(nextChain1, p);
    }
}

2.2 链路节点执行器 (基类,需要被继承)

需要使用责任链,都该继承ResponsibilityChainPathExecute,用来处理各节点的顺序执行

package com.pd.shopping.order.designptern.chain;

import org.springframework.stereotype.Component;

/**
 * @author hl
 */
@Component
public abstract class ResponsibilityChainPathExecute<P> {

    /**
     * 责任链中节点执行方法
     * @param p 执行方法的泛型参数
     */
    public abstract void execute(P p);

    /**
     *
     */
    private ResponsibilityChainPathExecute nextChain;

    /**
     * 设置 责任链下一个节点
     * @param next 下一个节点
     */
    public void setNextChain(ResponsibilityChainPathExecute next){
        this.nextChain = next;
    }

    /**
     * 获取 责任链下一个节点
     *
     * @return ResponsibilityChainPathExecute 执行器
     */
    public ResponsibilityChainPathExecute getNextChain(){
        return this.nextChain;
    }
}

三、订单业务 责任链 (案例一)

3.1 订单链抽象类 (组装链路、自定义订单公共方法)

链路节点执行使用了递归,所以在组装链路时,需要保证链路有始有终,不能循环依赖

SpringApplicationUtil为获取Bean的工具类,暂不提供,但可以用new 创建一个Bean

package com.pd.shopping.order.designptern.chain.order;

import com.pd.shopping.common.SpringApplicationUtil;
import com.pd.shopping.order.designptern.chain.*;
import org.springframework.stereotype.Component;

/**
 * @author hl
 */
@Component
public abstract class AbstractChainOrder<P> extends ResponsibilityChainPathExecute<P> {


    public static AbstractChainOrder chainPath(){
        //链开始节点 startCheck
        AbstractChainOrder startCheck = SpringApplicationUtil.getBean(ChainOrderCheck.class);
        AbstractChainOrder stock = SpringApplicationUtil.getBean(ChainOrderStock.class);
        AbstractChainOrder coupon = SpringApplicationUtil.getBean(ChainOrderCoupon.class);
        AbstractChainOrder integral = SpringApplicationUtil.getBean(ChainOrderIntegral.class);
        AbstractChainOrder shoppingCart = SpringApplicationUtil.getBean(ChainOrderShoppingCart.class);
        //链结束节点 endMsg
        AbstractChainOrder endMsg = SpringApplicationUtil.getBean(ChainOrderMsg.class);

        //链结束节点 endMsg
        shoppingCart.setNextChain(endMsg);
        integral.setNextChain(shoppingCart);
        coupon.setNextChain(integral);
        stock.setNextChain(coupon);
        //链开始节点 startCheck
        startCheck.setNextChain(stock);
        return startCheck;
    }

    public static AbstractChainOrder chainPath2(){
        //链开始节点 startCheck
        AbstractChainOrder startCheck = SpringApplicationUtil.getBean(ChainOrderCheck.class);
        AbstractChainOrder stock = SpringApplicationUtil.getBean(ChainOrderStock.class);
        //链结束节点 endMsg
        AbstractChainOrder endMsg = SpringApplicationUtil.getBean(ChainOrderMsg.class);

        stock.setNextChain(endMsg);
        startCheck.setNextChain(stock);
        return startCheck;
    }
}

3.2 链路节点-参数检查

package com.pd.shopping.order.designptern.chain.order;

import org.springframework.stereotype.Component;
import java.util.Map;

/**
 * @author hl
 */
@Component
public class ChainOrderCheck extends AbstractChainOrder<Map<String, Object>> {

    @Override
    public void execute(Map<String, Object> map) {
        System.out.println("ChainOrderCheck 参数检查," + map.get("goodsName").toString());
    }
}

3.3 链路节点-优惠券核销

package com.pd.shopping.order.designptern.chain.order;

import org.springframework.stereotype.Component;
import java.util.Map;

/**
 * @author hl
 */
@Component
public class ChainOrderCoupon extends AbstractChainOrder<Map<String, Object>> {

    @Override
    public void execute(Map<String, Object> map) {
        System.out.println("ChainOrderCoupon  优惠券核销," + map.get("goodsName").toString());
    }
}

3.4 链路节点-积分抵扣

package com.pd.shopping.order.designptern.chain.order;

import org.springframework.stereotype.Component;
import java.util.Map;

/**
 * @author hl
 */
@Component
public class ChainOrderIntegral extends AbstractChainOrder<Map<String, Object>> {

    @Override
    public void execute(Map<String, Object> map) {
        System.out.println("ChainOrderIntegral 积分抵扣," + map.get("goodsName").toString());
    }
}

3.5 链路节点-订单消息通知

package com.pd.shopping.order.designptern.chain.order;

import org.springframework.stereotype.Component;
import java.util.Map;

/**
 * @author hl
 */
@Component
public class ChainOrderMsg extends AbstractChainOrder<Map<String, Object>> {

    @Override
    public void execute(Map<String, Object> map) {
        System.out.println("ChainOrderMsg 订单消息通知," + map.get("goodsName").toString());
    }
}

3.6 链路节点-处理购物车

package com.pd.shopping.order.designptern.chain.order;

import org.springframework.stereotype.Component;
import java.util.Map;

/**
 * @author hl
 */
@Component
public class ChainOrderShoppingCart extends AbstractChainOrder<Map<String, Object>> {

    @Override
    public void execute(Map<String, Object> map) {
        System.out.println("ChainOrderShoppingCart 处理购物车," + map.get("goodsName").toString());
    }
}

3.7 链路节点-锁定库存

package com.pd.shopping.order.designptern.chain.order;

import org.springframework.stereotype.Component;
import java.util.Map;

/**
 * @author hl
 */
@Component
public class ChainOrderStock extends AbstractChainOrder<Map<String, Object>> {

    @Override
    public void execute(Map<String, Object> map) {
        System.out.println("ChainOrderStock 锁定库存," + map.get("goodsName").toString());
    }
}

四、审批业务 责任链 (案例二)

4.1 审批链抽象类 (组装链路、自定义审批公共方法)

链路节点执行使用了递归,所以在组装链路时,需要保证链路有始有终,不能循环依赖

package com.pd.shopping.order.designptern.chain.approve;

import com.pd.shopping.common.SpringApplicationUtil;
import com.pd.shopping.order.designptern.chain.ResponsibilityChainPathExecute;
import org.springframework.stereotype.Component;

/**
 * @author hl
 */
@Component
public abstract class AbstractChainApprove<P> extends ResponsibilityChainPathExecute<P> {

    public static AbstractChainApprove chainPath(){
        //链开始节点 startLeader
        AbstractChainApprove startLeader = SpringApplicationUtil.getBean(ChainApproveLeader.class);
        //链结束节点 endBoos
        AbstractChainApprove endBoos = SpringApplicationUtil.getBean(ChainApproveBoos.class);

        //链开始节点 startLeader
        startLeader.setNextChain(endBoos);
        return startLeader;
    }
}

4.2 链路节点-老板审批

package com.pd.shopping.order.designptern.chain.approve;

import com.pd.shopping.order.model.bo.ApproveContext;
import org.springframework.stereotype.Component;

/**
 * @author hl
 */
@Component
public class ChainApproveBoos extends AbstractChainApprove<ApproveContext> {

    @Override
    public void execute(ApproveContext context) {
        System.out.println("ChainApproveBoos 老板审批," + context.getBoosName());
    }
}

4.3 链路节点-经理审批

package com.pd.shopping.order.designptern.chain.approve;

import com.pd.shopping.order.model.bo.ApproveContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @author hl
 */
@Slf4j
@Component
public class ChainApproveLeader extends AbstractChainApprove<ApproveContext> {

    @Override
    public void execute(ApproveContext context) {
        System.out.println("ChainApproveBoos 经理审批," + context.getLeaderName());
    }
}

五、代码结构

责任链模式_第1张图片


六、调用


@GetMapping("/chainOrder")
public void chainOrder() {

    System.out.println("订单创建,链路1:");
    //下单参数
    Map<String,Object> map1 = new HashMap<>();
    map1.put("goodsName","比亚迪");
    //链路
    AbstractChainOrder chain1 = AbstractChainOrder.chainPath();
    ResponsibilityChain responsibilityChain1 = new ResponsibilityChain<AbstractChainOrder, Map<String,Object>>(chain1);
    responsibilityChain1.invoke(map1);


    System.out.println("订单创建,链路2:");
    Map<String,Object> map2 = new HashMap<>();
    map2.put("goodsName","长城");
    AbstractChainOrder chain2 = AbstractChainOrder.chainPath2();
    ResponsibilityChain responsibilityChain2 = new ResponsibilityChain<AbstractChainOrder, Map<String,Object>>(chain2);
    responsibilityChain2.invoke(map2);

    /* ********************************************************************** */

    System.out.println("审批,链路2:");
    ApproveContext approveContext = new ApproveContext();
    approveContext.setBoosName("张老板");
    approveContext.setLeaderName("李经理");
    AbstractChainApprove chainApprove = AbstractChainApprove.chainPath();
    ResponsibilityChain responsibilityChain3 = new ResponsibilityChain<AbstractChainApprove, ApproveContext>(chainApprove);
    responsibilityChain3.invoke(approveContext);

}

执行日志

订单创建,链路1ChainOrderCheck 参数检查,比亚迪
ChainOrderStock 锁定库存,比亚迪
ChainOrderCoupon  优惠券核销,比亚迪
ChainOrderIntegral 积分抵扣,比亚迪
ChainOrderShoppingCart 处理购物车,比亚迪
ChainOrderMsg 订单消息通知,比亚迪
订单创建,链路2ChainOrderCheck 参数检查,长城
ChainOrderStock 锁定库存,长城
ChainOrderMsg 订单消息通知,长城

审批,链路2ChainApproveBoos 经理审批,李经理
ChainApproveBoos 老板审批,张老板

你可能感兴趣的:(设计模式,责任链模式,java,设计模式)