项目背景
小明操作公司的采购员,需要去采购一批电脑,通过对市场的调研之后,需要提交申请走审批流程拨款购买。审批的决策因素是采用电脑的总价。小于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 **
总结
优点:
- 将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求
- 可以简化对象,因为它无须知道链的结构
- 可以动态地增加或删减处理请求的链结构
缺点:
- 请求从链的开头进行遍历,对性能有一定的损耗
- 并不保证请求一定被处理
适用场合:
- 有多个对象可以处理一个请求
- 不明确接收者的情况
- 有序、无序链,线型、树形、环形链
责任链模式和状态模式主要区别:
- 责任链模式注重请求的传递
- 状态模式注重对象状态的转换