Table of Contents generated with DocToc
笔记来源:尚硅谷设计模式
一、需求
学校OA系统的采购审批项目:需求是
- 采购员采购教学器材
- 如果金额小于等于5000,由教学主任审批
- 如果金额小于等于10000,由院长审批
- 如果金额小于等于30000,由副校长审批
- 如果金额超过30000以上,有校长审批
二、传统的设计方案
传统方式是:接收到一个采购请求后,根据采购金额【if-else】来调用对应的Approver (审批人)完成审批。
问题:
- 当审批金额发生了变化。那么则要更改if-else的代码,如果条件很复杂,修改起来很困难
- 客户端必须明确的知道有多少个审批级别,并且对应的金额
Client和aprrover有强耦合关系
三、职责链模式
职责链模式(Chain of Responsibility Pattern),又叫责任链模式,为请求创建了一个接收者对象的链(简单示意图)。 这种模式对请求的发送者和接收者进行解耦。
我们将处理请求发送给教务主任,如果可以处理就处理,如果不能处理就交给下一个角色(院长),如果院长可以处理就处理,如果不能处理就交给下一个角色(副校长),直到校长。
首先先写好请求类:
public class PurchaseRequest {
private double price=0.0f;//金额
private int id;
public PurchaseRequest(double price, int id) {
this.price = price;
this.id = id;
}
/*get set省略*/
}
然后创建虚拟的解决类(相当于处理者):
public abstract class Handler {
Handler successor;//保存下一个处理者
String name;
public Handler(String name) {
this.name = name;
}
//处理审批请求的方法,得到一个请求,处理是子类完成,因此该方法做成抽象
public abstract void processRequest(PurchaseRequest request) throws Exception;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
}
然后用子类继承,并实现处理方法(此处以系主任为例):
//系主任
public class DepartmentApprover extends Handler{
public DepartmentApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) throws Exception {
if(request.getPrice() <= 5000)
System.out.println("请求编号为"+request.getId()+"被"+this.name+"处理");
//如果不满足条件,则丢给下一个处理者
else
successor.processRequest(request);
}
}
在Client中生成责任链,并发送请求【切记责任链要设计成环状,万一有个1000元的需求从中间责任人(比如副校长)开始处理,也能够传递到系主任】
public class Client {
public static void main(String[] args) throws Exception {
PurchaseRequest request = new PurchaseRequest(3500,1);
Handler departmentApprover = new DepartmentApprover("系主任");
Handler collegeApprover = new CollegeApprover("院长");
Handler viceSchoolApprover = new ViceSchoolApprover("副校长");
Handler schoolApprover = new SchoolApprover("校长");
//设置责任链(处理人构成环状)
schoolApprover.setSuccessor(departmentApprover);
viceSchoolApprover.setSuccessor(schoolApprover);
collegeApprover.setSuccessor(viceSchoolApprover);
departmentApprover.setSuccessor(collegeApprover);
departmentApprover.processRequest(request);
}
}
输出为:
请求编号为1被系主任处理
整个实例类图为: