设计模式 总目录
https://preparedata.blog.csdn.net/article/details/134512591
文章目录
-
- [设计模式 总目录](#设计模式 总目录)
- 一、案例
- 二、责任链
-
- [2.1 责任链生成类](#2.1 责任链生成类)
- [2.2 链路节点执行器 (基类,需要被继承)](#2.2 链路节点执行器 (基类,需要被继承))
- [三、订单业务 责任链 (案例一)](#三、订单业务 责任链 (案例一))
-
- [3.1 订单链抽象类 (组装链路、自定义订单公共方法)](#3.1 订单链抽象类 (组装链路、自定义订单公共方法))
- [3.2 链路节点-参数检查](#3.2 链路节点-参数检查)
- [3.3 链路节点-优惠券核销](#3.3 链路节点-优惠券核销)
- [3.4 链路节点-积分抵扣](#3.4 链路节点-积分抵扣)
- [3.5 链路节点-订单消息通知](#3.5 链路节点-订单消息通知)
- [3.6 链路节点-处理购物车](#3.6 链路节点-处理购物车)
- [3.7 链路节点-锁定库存](#3.7 链路节点-锁定库存)
- [四、审批业务 责任链 (案例二)](#四、审批业务 责任链 (案例二))
-
- [4.1 审批链抽象类 (组装链路、自定义审批公共方法)](#4.1 审批链抽象类 (组装链路、自定义审批公共方法))
- [4.2 链路节点-老板审批](#4.2 链路节点-老板审批)
- [4.3 链路节点-经理审批](#4.3 链路节点-经理审批)
- 五、代码结构
- 六、调用
一、案例
个人理解责任链模式在于,将业务功能拆分成各节点(职责节点),再打包成有顺序性的链路。
如果节点处理成功,可进入下一节点 。以下示例代码未包含此逻辑,但可在基类中添加状态来实现,偷个懒,暂不实现了。
案例一:订单创建
订单创建,可能会包含参数检查、锁定库存、优惠券核销、积分抵扣、处理购物车、订单消息通知
等逻辑
但不同的订单类型可能包含的节点不同或顺序。现在可以将订单创建逻辑拆分。
不同的订单类型 可以提现设置不同的执行链路来处理订单。
如后续需添加节点或删除节点。也能快速适配
案例一:审批
审批流程,可能会包含组长、经理、行政、老板
等逻辑
但不同的审批业务可能包含的节点不同或顺序。现在可以将逻辑拆分。
不同的审批业务 可以提现设置不同的执行链路来处理。
二、责任链
2.1 责任链生成类
利用泛型 T
来约束子类中需继承ResponsibilityChainPathExecute
利用泛型 P
来泛型化处理节点执行的参数, 实际业务中,可以将订单创建、审批相差很大的业务使用上下文来处理节点执行的参数
链路节点执行使用了递归
invoke(ResponsibilityChainPathExecute nextChain, P p) ,所以在组装链路时,需要保证链路有始有终,不能循环依赖
java
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,用来处理各节点的顺序执行
java
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
java
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 链路节点-参数检查
java
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 链路节点-优惠券核销
java
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 链路节点-积分抵扣
java
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 链路节点-订单消息通知
java
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 链路节点-处理购物车
java
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 链路节点-锁定库存
java
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 审批链抽象类 (组装链路、自定义审批公共方法)
链路节点执行使用了递归
,所以在组装链路时,需要保证链路有始有终,不能循环依赖
java
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 链路节点-老板审批
java
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 链路节点-经理审批
java
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());
}
}
五、代码结构
六、调用
java
@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);
}
执行日志
java
订单创建,链路1:
ChainOrderCheck 参数检查,比亚迪
ChainOrderStock 锁定库存,比亚迪
ChainOrderCoupon 优惠券核销,比亚迪
ChainOrderIntegral 积分抵扣,比亚迪
ChainOrderShoppingCart 处理购物车,比亚迪
ChainOrderMsg 订单消息通知,比亚迪
订单创建,链路2:
ChainOrderCheck 参数检查,长城
ChainOrderStock 锁定库存,长城
ChainOrderMsg 订单消息通知,长城
审批,链路2:
ChainApproveBoos 经理审批,李经理
ChainApproveBoos 老板审批,张老板