天天看点

java——职责链模式

  今天小咸儿来总结一下最近学习的职责链模式:

职责链模式:为某个请求创建一个对象链。每个对象依序检查此请求,并对其进行处理,或者将它传给链中的下一个对象。

从图中可以很清楚的看出职责链模式的工作流程:

职责链电子邮件示例图:

java——职责链模式

在此,小咸儿以一个具体的实例来进行思路讲解。

  实例:比如说,在购买物资时,需要将采购单提交上自己的上一级部分主任进行审批,如果权限不够则继续递交给经理,还不够则继续递交给总经理,还没有权限则递交给董事。批准后发钱去购买物资。在这个过程中,我只需要提交我的请求给我的部门主任,具体审批过程,有谁最终审批我不关心,我只需要等待审批的结果就够了。

  接下来,先看一下代码:

请求类:采购申请单

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生成的对应类图如下:

职责链类图:

java——职责链模式

  在进行了代码实践以后,小咸儿对于职责链模式有了更进一步的了解。在此来看一下职责链模式的优缺点:

职责链的优点:

  • 将请求的发送者和接收者解耦。
  • 可以简化请求的对象,因为他不需要知道链的结构。
  • 通过改变链内的成员或调动他们的次序,允许你动态的新增或者删除责任节点。

责任链的用途和缺点:

  • 经常被使用在窗口系统中,处理鼠标和键盘类的事件。
  • 并不保证请求一定会执行,如果没有任何对象处理它的话,则会落到链尾端之外。(这可以是优点可以是缺点)
  • 可能不容易观察运行时的特征,有碍于除错。

  除此例之外,还有Tomcat中的Filter就是使用了职责链模式,创建一个Filter除了要在web.xml文件中做相应配置外,还需要实现Javax.servlet.Filter接口。

参考博客:JAVA职责链模式