这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
项目背景
小明操作公司的采购员,需要去采购一批电脑,通过对市场的调研之后,需要提交申请走审批流程拨款购买。审批的决策因素是采用电脑的总价。小于5000,组长审批就ok了,5000-10000需要部长审批,10000-50000需要副总裁审批,50000以上需要总裁审批。
考虑到扩展性,我们下面思考下如何设计?
第一,影响决策因素:价格
第二,决策级别:组长、部长、副总、总裁
接下来,我们责任链模式隆重登场了。
什么是责任链模式?
责任链模式为请求创建了一个接收者对象的链。通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
责任链的意图
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
主要解决的问题
职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
代码示例
下面示例代码走起,首先定义采购对象:
// 采购
public class PurchaseRequest {
// 采购类型
private int type = 0;
// 采购数量
private int number = 0;
// 采购单价
private float price = 0;
// 采购ID
private int id = 0;
public PurchaseRequest(int type, int number, float price) {
this.type = type;
this.number = number;
this.price = price;
}
public int getType() {
return type;
}
public float getSum() {
return number * price;
}
public int getId() {
return (int) (Math.random() * 1000);
}
}
然后抽象出来一个审批父类:
@Getter
@Setter
public abstract class Approver {
// 下一个审批者
protected Approver successor;
private String name;
public Approver(String name) {
this.name=name;
}
public abstract void processRequest(PurchaseRequest request);
}
下面依次实现组长、部长、副总裁、总裁审批:
package com.lgd.design.chain;
// 组审批
public class GroupApprover extends Approver {
public GroupApprover(String Name) {
super(Name + " GroupLeader");
}
@Override
public void processRequest(PurchaseRequest request) {
if (request.getSum() < 5000) {
System.out.println("**This request " + request.getId() + " will be handled by " + this.getName() + " **");
} else {
successor.processRequest(request);
}
}
}
package com.lgd.design.chain;
// 部门审批
public class DepartmentApprover extends Approver {
public DepartmentApprover(String Name) {
super(Name + " DepartmentLeader");
}
@Override
public void processRequest(PurchaseRequest request) {
if ((5000 <= request.getSum()) && (request.getSum() < 10000)) {
System.out.println("**This request " + request.getId() + " will be handled by " + this.getName() + " **");
} else {
successor.processRequest(request);
}
}
}
package com.lgd.design.chain;
// 副总裁审批
public class VicePresidentApprover extends Approver {
public VicePresidentApprover(String name) {
super(name + " Vice President");
}
@Override
public void processRequest(PurchaseRequest request) {
if ((10000 <= request.getSum()) && (request.getSum() < 50000)) {
System.out.println("**This request " + request.getId() + " will be handled by " + this.getName() + " **");
} else {
successor.processRequest(request);
}
}
}
package com.lgd.design.chain;
// 总裁审批
public class PresidentApprover extends Approver {
public PresidentApprover(String Name) {
super(Name + " President");
}
@Override
public void processRequest(PurchaseRequest request) {
if (50000 <= request.getSum()) {
System.out.println("**This request " + request.getId() + " will be handled by " + this.getName() + " **");
} else {
successor.processRequest(request);
}
}
}
最后测试审批流程:
package com.lgd.design.chain;
public class MainTest {
public static void main(String[] args) {
Approver groupApprover = new GroupApprover("Tom");
Approver departmentApprover = new DepartmentApprover("Jerry");
Approver vicePresidentApprover = new VicePresidentApprover("Kate");
Approver presidentApprover = new PresidentApprover("Bush");
groupApprover.setSuccessor(vicePresidentApprover);
departmentApprover.setSuccessor(presidentApprover);
vicePresidentApprover.setSuccessor(departmentApprover);
presidentApprover.setSuccessor(groupApprover);
vicePresidentApprover.processRequest(new PurchaseRequest(1, 100, 40));
vicePresidentApprover.processRequest(new PurchaseRequest(2, 200, 40));
vicePresidentApprover.processRequest(new PurchaseRequest(3, 300, 40));
vicePresidentApprover.processRequest(new PurchaseRequest(4, 400, 140));
}
}
运行结果:
**This request 331 will be handled by Tom GroupLeader **
**This request 504 will be handled by Jerry DepartmentLeader **
**This request 309 will be handled by Kate Vice President **
**This request 473 will be handled by Bush President **
总结
优点:
- 将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求
- 可以简化对象,因为它无须知道链的结构
- 可以动态地增加或删减处理请求的链结构
缺点:
- 请求从链的开头进行遍历,对性能有一定的损耗
- 并不保证请求一定被处理
适用场合:
- 有多个对象可以处理一个请求
- 不明确接收者的情况
- 有序、无序链,线型、树形、环形链
责任链模式和状态模式主要区别:
- 责任链模式注重请求的传递
- 状态模式注重对象状态的转换