今天小咸儿来总结一下最近学习的职责链模式:
职责链模式:为某个请求创建一个对象链。每个对象依序检查此请求,并对其进行处理,或者将它传给链中的下一个对象。
从图中可以很清楚的看出职责链模式的工作流程:
职责链电子邮件示例图:
在此,小咸儿以一个具体的实例来进行思路讲解。
实例:比如说,在购买物资时,需要将采购单提交上自己的上一级部分主任进行审批,如果权限不够则继续递交给经理,还不够则继续递交给总经理,还没有权限则递交给董事。批准后发钱去购买物资。在这个过程中,我只需要提交我的请求给我的部门主任,具体审批过程,有谁最终审批我不关心,我只需要等待审批的结果就够了。
接下来,先看一下代码:
请求类:采购申请单
package pattern.builder.chain;
/**
* 采购申请单(请求类)
* @author Phyllis
* @since 2019年6月18日14:55:34
*/
public class PurchaseRequest {
/**
* 采购目的
*/
private String purpose;
/**
* 采购单号
*/
private int number;
/**
* 采购总价
*/
private double amount;
public PurchaseRequest(String purpose, int number,double amount){
this.purpose = purpose;
this.number = number;
this.amount = amount;
}
public String getPurpose() {
return purpose;
}
public void setPurpose(String purpose) {
this.purpose = purpose;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
}
抽象审批类:
package pattern.builder.chain;
/**
* 抽象审批类:处理请求和跳转请求
* @author Phyllis
* @since 2019年6月18日15:02:05
*/
public abstract class Approver {
/**
* 定义下一个处理对象
*/
protected Approver success;
/**
* 定义下一个对象的名字
*/
protected String name;
public Approver(String name) {
this.name = name;
}
// 创建链
public void setApprover(Approver approver) {
this.success = approver;
}
public abstract void handlePurchaseRequest(PurchaseRequest purchaseRequest);
}
具体实现类:部门主任,审批的第一个节点
package pattern.builder.chain;
/**
* 主任类:第一个审批节点
* @author Phyllis
* @since 2019年6月18日15:07:49
*/
public class Director extends Approver{
public Director(String name){
super(name);
}
@Override
public void handlePurchaseRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getAmount() < 10000){
System.out.println("部门主任"+this.name+"通过了采购单"+purchaseRequest.getNumber()+"金额"+purchaseRequest.getAmount()+"用于"+purchaseRequest.getPurpose());
} else {
// 权限不够,传递给下一级审批人
this.success.handlePurchaseRequest(purchaseRequest);
}
}
}
具体实现类:经理,审批的第二个节点
package pattern.builder.chain;
/**
* 经理:第二个审批节点
* @author Phyllis
* @since 2019年6月18日15:14:33
*/
public class Manager extends Approver{
public Manager(String name){
super(name);
}
@Override
public void handlePurchaseRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getAmount() < 50000){
System.out.println("经理"+this.name+"同意了采购单"+purchaseRequest.getNumber()+"金额"+purchaseRequest.getAmount()+"用于"+purchaseRequest.getPurpose());
}else {
// 权限不够,传递给下一个审批人
this.success.handlePurchaseRequest(purchaseRequest);
}
}
}
具体实现类:总经理,审批的第三个节点
package pattern.builder.chain;
/**
* 总经理:第三个审批节点
* @author Phyllis
* @since 2019年6月18日15:14:33
*/
public class President extends Approver{
public President(String name){
super(name);
}
@Override
public void handlePurchaseRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getAmount() < 100000){
System.out.println("总经理"+this.name+"同意了采购单"+purchaseRequest.getNumber()+"金额"+purchaseRequest.getAmount()+"用于"+purchaseRequest.getPurpose());
}else {
// 权限不够,传递给下一个审批人
this.success.handlePurchaseRequest(purchaseRequest);
}
}
}
具体实现类:董事,审批的最后一个节点
package pattern.builder.chain;
/**
* 总经理:第三个审批节点
* @author Phyllis
* @since 2019年6月18日15:14:33
*/
public class President extends Approver{
public President(String name){
super(name);
}
@Override
public void handlePurchaseRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getAmount() < 100000){
System.out.println("总经理"+this.name+"同意了采购单"+purchaseRequest.getNumber()+"金额"+purchaseRequest.getAmount()+"用于"+purchaseRequest.getPurpose());
}else {
// 权限不够,传递给下一个审批人
this.success.handlePurchaseRequest(purchaseRequest);
}
}
}
客户端:设置审批人,发送请求
package pattern.builder.chain;
/**
* 职责链模式的客户端
* @author Phyllis
* @since 2019年6月18日15:22:55
*/
public class Client {
public static void main(String[] args){
Approver a1,a2,a3,a4;
a1 = new Director("海贼王");
a2 = new Manager("葫芦娃");
a3 = new President("黑猫警长");
a4 = new Congress("花仙子");
// 创建审批链
a1.setApprover(a2);
a2.setApprover(a3);
a3.setApprover(a4);
// 创建单据
PurchaseRequest p1 = new PurchaseRequest("购买船只", 10001,9999);
a1.handlePurchaseRequest(p1);
p1 = new PurchaseRequest("购买蛇精",10002,49999);
a1.handlePurchaseRequest(p1);
p1 = new PurchaseRequest("购买白猫",10003,99999);
a1.handlePurchaseRequest(p1);
p1 = new PurchaseRequest("购买种子",10004,912478950);
a1.handlePurchaseRequest(p1);
}
}
根据此实例由idea生成的对应类图如下:
职责链类图:
在进行了代码实践以后,小咸儿对于职责链模式有了更进一步的了解。在此来看一下职责链模式的优缺点:
职责链的优点:
- 将请求的发送者和接收者解耦。
- 可以简化请求的对象,因为他不需要知道链的结构。
- 通过改变链内的成员或调动他们的次序,允许你动态的新增或者删除责任节点。
责任链的用途和缺点:
- 经常被使用在窗口系统中,处理鼠标和键盘类的事件。
- 并不保证请求一定会执行,如果没有任何对象处理它的话,则会落到链尾端之外。(这可以是优点可以是缺点)
- 可能不容易观察运行时的特征,有碍于除错。
除此例之外,还有Tomcat中的Filter就是使用了职责链模式,创建一个Filter除了要在web.xml文件中做相应配置外,还需要实现Javax.servlet.Filter接口。
参考博客:JAVA职责链模式