天天看點

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職責鍊模式