- 笔记来自《秒懂设计模式》
一、简单的生产线
最简单的责任链模式例子:汽车生产线的制造流程。
我们将汽车生产线从左至右分为3个功能节点:
这样将产品逐级传递,每经过一个节点就完成一部分工作,最终完成产品交付。
二、工作流程拆分
带有一些逻辑的责任链:报销审批流程。
审批流程按负责人或者工作职责进行拆分:需要依次通过财务专员、财务经理、财务总监的审批。如果申请金额在审批人的审批职权范围内则审批通过并终止流程,反之则会升级至更高层级的上级去继续审批,直至最终的财务总监,如果仍旧超出财务总监的审批金额则驳回申请,流程终止。
如何设计这个审批流程:
首先按角色对业务进行拆分,将不同的业务代码放在不同的角色类中,如此达到职权分拆的目的,可扩展性、可维护性也能得到提高。
.
三、踢皮球
1. 实例
- 基于上述审批流程,来做一个简单的实例:假设某公司的报销审批流程有3个审批角色
2. 代码
Staff
/**
* 财务专员类
*/
public class Staff {
private String name;
public Staff(String name){
this.name = name;
}
public boolean approve(int amount) {
if (amount <= 1000) {
System.out.println("审批通过。【专员:" + name + "】");
return true;
} else {
System.out.println("无权审批,请找上级。【专员:" + name + "】");
return false;
}
}
}Manager
/**
* 财务经理类
*/
public class Manager {
private String name;
public Manager(String name){
this.name = name;
}
public boolean approve(int amount) {
if (amount <= 5000) {
System.out.println("审批通过。【经理:" + name + "】");
return true;
} else {
System.out.println("无权审批,请找上级。【经理:" + name + "】");
return false;
}
}
}CFO
/**
* 财务总监类
*/
public class CFO {
private String name;
public Manager(String name){
this.name = name;
}
/* 定义了财务总监类CFO的审批方法approve()并接受要审批的金额,
如果金额在10000元以内则审批通过,否则驳回此申请。 */
public boolean approve(int amount) {
if (amount <= 10000) {
System.out.println("审批通过。【总监:" + name + "】");
return true;
} else {
System.out.println("驳回申请。【总监:" + name + "】");
return false;
}
}
}3个审批角色的代码都比较类似,只要超过其审批金额的权限就驳回申请,反之则审批通过。
接下来,客户端开始提交申请了:Client
/**
* 客户端类
*/
public class Client {
public static void main(String[] args){
int amount = 10000; // 出差花费10000元
// 先找专员张飞审批
Staff staff = new Staff("张飞");
if (!staff.approve(amount)) {
// 被驳回,找关二爷问问
Manager manager = new Manager("关羽");
if (!manager.approve(amount)){
// 还是被驳回,只能找老大了
CFO cfo = new CFO("刘备");
cfo.approve(amount);
}
}
}
}
/*******************************
无权审批,请找上级。【专员:张飞】
无权审批,请找上级。【经理:关羽】
审批通过。【总监:刘备】
*******************************/
3. 问题
类似如上环环相扣的传递机制,就需要我们搭建一个链式结构的工作流,这也是责任链模式的精髓之所在。
.
四、架构工作流
我们用抽象类来定义审批人:
- 审批人 Approver
public abstract class Approver {
protected String name; // 抽象出审批人的姓名
protected Approver nextApprover; // 下一位审批人,更高级别的领导
public Approver(String name){
this.name = name;
}
protected Approver setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
return this.nextApprover; // 返回下一位审批人,使其支持链式编程
}
public abstract void approve(int amount); // 抽象审批方法由具体审批人子类实现
/*
* 由于审批人在无权审批时需要传递业务给其上级领导,因此我们在第4行定义上级领导的引用nextApprover,与下一位审批人串联起来,同时将其注入第10行。
* 当然,每位审批人的角色不同,其审批逻辑也有所区别,所以我们在第15行对审批方法进行抽象,交由具体的子类审批角色去继承和实现。
*/
}
接着对3个审批角色的代码进行重构:
Staff
/**
* 财务专员类
*/
public class Staff extends Approver {
public Staff(String name) {
super(name);
}
@Override
public void approve(int amount) {
if(amount <= 1000) {
System.out.println("审批通过。【专员:" + name + "】");
} else {
System.out.println("无权审批,升级处理。【专员:" + name + "】");
this.nextApprover.approve(amount);
}
}
}
/* 财务专员类继承了审批人抽象类并实现了审批方法approve(),
接收到报销申请金额后自第9行开始申明自己的审批权限为1000元,
若超出则调用自己上级领导的审批方法nextApprover() ,将审批业务传递下去。*/Manager
/**
* 财务经理类
*/
public class Manager extends Approver {
public Manager(String name) {
super(name);
}
@Override
public void approve(int amount) {
if(amount <= 5000) {
System.out.println("审批通过。【经理:" + name + "】");
} else {
System.out.println("无权审批,升级处理。【经理" + name + "】");
this.nextApprover.approve(amount);
}
}
}CFO
/**
* 财务专员类
*/
public class CFO extends Approver {
public CFO(String name) {
super(name);
}
@Override
public void approve(int amount) {
if(amount <= 1000) {
System.out.println("审批通过。【财务总监:" + name + "】");
} else {
System.out.println("驳回申请。【财务总监:" + name + "】");
}
}
}
/* 比较特殊的审批人是责任链末节点的财务总监类,最高职级的财务总监CFO的审批逻辑略有不同,
当申请金额超出10000元后就再有下一个审批人了,所以此时就会驳回报销申请。*//**
* 财务专员类
*/
public class CFO extends Approver {
public CFO(String name) {
super(name);
}
@Override
public void approve(int amount) {
if(amount <= 1000) {
System.out.println("审批通过。【财务总监:" + name + "】");
} else {
System.out.println("驳回申请。【财务总监:" + name + "】");
}
}
}
/* 比较特殊的审批人是责任链末节点的财务总监类,最高职级的财务总监CFO的审批逻辑略有不同,
当申请金额超出10000元后就再有下一个审批人了,所以此时就会驳回报销申请。*/Client
/**
* 客户端类
*/
public class Client {
public static void main(String[] args){
Aprrovrt flightJohn = new Staff("张飞");
// 此处使用链式编程配置责任链
flightJogn.setNextApprover(new Manager("关羽")).setNextApprover(new CFO("刘备"));
// 直接找专员张飞审批
flightJohn.approve(1000);
/************************
审批通过。【专员:张飞】
************************/
flightJohn.approve(4000);
/************************
无权审批,升级处理。【专员:张飞】
审批通过。【经理:关羽】
************************/
flightJohn.approve(9000);
/************************
无权审批,升级处理。【专员:张飞】
无权审批,升级处理。【专员:关羽】
审批通过。【CEO:刘备】
************************/
flightJohn.approve(9000);
/************************
无权审批,升级处理。【专员:张飞】
无权审批,升级处理。【专员:关羽】
驳回申请。【CEO:刘备】
************************/
}
}至此,以责任链模式为基础架构的工作流搭建完成:
- 各审批角色:只需要定义其职权范围内的工作,再依靠高层抽象实现角色责任的链式结构,审批逻辑得以拆分、串联,让业务申请在责任链上逐级传递。
- 申请人:再也不必关心业务处理细节与结果了,彻底将工作流或业务逻辑抛开,轻松地将申请递交给责任链入口即可得到最终结果。
五、让业务飞一会儿
1. 类结构
责任链模式的类结构:
v1.5.2