责任链模式是行为模式的一种,它将需要触发的Handler组成一条链,发送者将请求发给链的第一个接收者,并且沿着这条链传递,直到有一个Handler来处理它或者直到最后也没有对象处理而留在链末尾端;责任连模式的重点是在链上,由一条链去处理相似的请求,在链中决定谁来处理这个请求
责任链分为纯责任链与不纯责任链(一般实战应用较多)
纯责任链的代码Demo:
/**
* 在公司OA系统请假审批流程
如果请假小于3天只需要项目经理批复就行;
如果请假大于等于3天,小于7天需要人事经理批复了;
如果请假大于等于7天,小于15天需要总经理批复了;
如果申请请假大于等于15天,决绝批复......
* @param args
*/
public static void main(String[] args) {
Leader manager = new Manager("张三");
Leader hrManager = new HrManager("李四");
Leader generalManager = new GeneralManager("王麻子");
//组织责任链对象的关系
manager.setNextLeader(hrManager);
hrManager.setNextLeader(generalManager);
//请假
LeaveRequest request = new LeaveRequest("parry", 10, "回家相亲!");
manager.dealLeaveRequest(request);
}
public abstract class Leader {
// 领导姓名
protected String name;
// 责任链上的后继对象
protected Leader nextLeader;
public Leader(String name) {
super();
this.name = name;
}
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}
public abstract void dealLeaveRequest(LeaveRequest request);
}
public class HrManager extends Leader{
public HrManager(String name) {
super(name);
}
@Override
public void dealLeaveRequest(LeaveRequest request) {
if (3 <= request.getLeaveDay() && request.getLeaveDay() < 7) {
System.out.println("人事经理:" + name + " 审批了 " + request.getEmployee() + "请假" + request.getLeaveDay()
+ "天的请求,请假原因:" + request.getReason());
} else {
if (this.nextLeader != null) {
this.nextLeader.dealLeaveRequest(request);
}
}
}
}
public class GeneralManager extends Leader {
public GeneralManager(String name) {
super(name);
}
@Override
public void dealLeaveRequest(LeaveRequest request) {
if (7 <= request.getLeaveDay() && request.getLeaveDay() <= 15) {
System.out.println("总经理:" + name + " 审批了 " + request.getEmployee() + "请假" + request.getLeaveDay()
+ "天的请求,请假原因:" + request.getReason());
} else {
System.out.println(
"总经理:" + name + " 拒绝了 " + request.getEmployee() + "请假" + request.getLeaveDay() + "天的请求,请假不能超过15天");
}
}
}
public class Manager extends Leader{
public Manager(String name) {
super(name);
}
@Override
public void dealLeaveRequest(LeaveRequest request) {
if (request.getLeaveDay() < 3) {
System.out.println("经理:" + name + " 审批了 " + request.getEmployee() + "请假" + request.getLeaveDay()
+ "天的请求,请假原因:" + request.getReason());
} else {
if (this.nextLeader != null) {
this.nextLeader.dealLeaveRequest(request);
}
}
}
}
@Data
public class LeaveRequest {
//姓名
private String name;
//请假天数
private int leaveDay;
//请假原因
private String reason;
public LeaveRequest(String name, int leaveDay, String reason) {
this.name=name;
this.leaveDay=leaveDay;
this.reason=reason;
}
}
电商售后使用责任链(不纯责任链)
售后业务梳理
电商售后常见三种模式:
仅退款、退款退货、退款换货
售后业务可分为
仅退款: 采购商申请——>商家审核——>完成
退款退货:采购商申请——>商家审核——>采购商发货——>商家确认收货——>完成
退款换货:采购商申请——>商家审核——>采购商发货——>商家确认收货——>商家发出新品——>采购商确认收货——>完成
仅退款的实际退款等操作在商家审核时,而退款退货和退款换货则在确认收货时。
以下为售后责任链流程:
售后->校验退款单状态->原路退款(以下单支付方式为准)->退积分或其它优惠->更新订单及对应商品退款信息->保存结算->保存财务流水->保存/更新退款日志->发送退款成功异步消息
三种售后的核心退款业务流程基本是一致的,少个别节点业务逻辑有所区别,将核心业务抽成责任链的各个节点,这对售后来说,代码的复用性提高了很多,同时业务处理更加清晰,犯错率大大降低。
以下为售后中代码使用Demo
定义一个节点的基类接口
public interface BaseRefundHandler {
void handle(PipelineContext context) ;
}
售后责任链组装,以下以仅退款为例
public class RefundPipeBean {
/**
* 仅退款,责任链初始化节点
*/
public List<String> refundPipe = new ArrayList<>();
public List<String> getRefundPipe() {
refundPipe.add("checkRefundStatus"); //校验退款单状态
refundPipe.add("refundMoney"); //原路退款(获取订单支付方式)
refundPipe.add("returnScore"); //退积分或其它优惠券类
......
return refundPipe;
}
@Bean
@Scope("prototype")
public CheckRefundStatus checkRefundStatus() {return new CheckRefundStatus();}
@Bean
@Scope("prototype")
public RefundMoney refundMoney() {return new RefundMoney();}
......
}
** 注: 这个配置就等同于之前在xml里的配置**
"checkRefundStatus" class="com.xx.CheckRefundStatus"/>
创建一个启动监听器
@Component
public class RefundPipeListener extends ApplicationObjectSupport implements InitializingBean {
private static Map<String, List> handlersMap = new HashMap<>();
public static Map<String, List> getHandlersMap() {
return handlersMap;
}
//最好定义成全局的,此处因演示 才在类中写 。 责任链的名称
public static String ONLY_REFUND="ONLY_REFUND";
@Override
public void afterPropertiesSet() throws Exception {
RefundPipeBean refundPipeBean=new RefundPipeBean();
//装载退款业务链.....
List normalHandlers=new ArrayList<>();
for (String s : refundPipeBean.getRefundPipe()) {
BaseRefundHandler normalHandler = (BaseRefundHandler) getApplicationContext().getBean(s);
normalHandlers.add(normalHandler);
handlersMap.put(ONLY_REFUND, normalHandlers);
}
}
}
创建节点传递对象所用POJO类
@Data
public class PipelineContext<K, V> extends ConcurrentHashMap<K, V> {
protected boolean success = false;
//责任链结束标识
protected boolean isEnd = false;
protected String resultCode;
private Object data;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public boolean isEnd() {
return isEnd;
}
public void setEnd(boolean end) {
isEnd = end;
}
}
public class RefundPipelineContext<K, V> extends PipelineContext<K, V> {
/**
* 封装退款单信息
*/
private RefundInfoPipeVo refundInfoPipeVo;
public RefundInfoPipeVo getRefundInfoPipeVo() {
return refundInfoPipeVo;
}
public void setRefundInfoPipeVo(RefundInfoPipeVo refundInfoPipeVo) {
this.refundInfoPipeVo = refundInfoPipeVo;
}
}
创建节点
public class CheckRefundStatus implements BaseRefundHandler {
@Override
public void handle(PipelineContext<String, RefundInfoPipeVo> context) {
//业务逻辑 todo
......
//表示该节点运行正常,可以继续向下走
context.setSuccess(true);
}
}
业务调用层
@RestController
public class RefundInfoController {
@Autowired
RefundInfoService refundInfoService;
@ApiOperation("仅退款")
@RequestMapping(value = "/auditRefund", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=UTF-8")
public RespData<Boolean> auditRefund(xxx) {
refundInfoService.auditRefund(xxx);
return RespData.success("审核成功",true);
}
}
public interface RefundInfoService {
void auditRefund(xxx);
}
@Service("refundInfoService")
public class RefundInfoServiceImpl implements RefundInfoService {
@Override
public void auditRefund(xxx) {
//业务逻辑 todo
RefundInfoResultVo refundInfoResultVo = refundInfoMapper.queryById(platformId, refundId);
......
PipelineContext<String, RefundInfoPipeVo> refund = new RefundPipelineContext<>();
//在责任链中传递参数对象
refund.put("refund", refundInfoResultVo);
Map<String, List> map = RefundPipelineChangeListener.getHandlersMap();
//通过责任链的名称获取对应链 。 此处key值应为一个全局的常量,与上面监听器中的链条名一致
List baseRefundHandlers = map .get(ONLY_REFUND);
for (BaseRefundHandler handler : baseRefundHandlers) {
handler.handle(refund);
if (refund.isEnd()) {
System.out.println("责任链执行结束...");
break;
}
if (!refund.isSuccess()) {
System.out.println("责任链执行失败...");
break;
}
}
}
}
整体总结
以上是责任链在业务中创建及使用的流程。
同时以上流程也还存在一些可优化点:
全部0条评论
快来发表一下你的评论吧 !