1. 程式人生 > >職責鏈初步理解及應用小demo

職責鏈初步理解及應用小demo

什麼是職責鏈

先看個需要用到職責的場景:

if(請假天數 <= 1){
    askForLeave(小組長);
}else if(請假天數 <= 3  &&  請假天數 > 1){
    askForLeave(專案經理);
}else if(請假天數 <= 7  &&  請假天數 > 3){
    askForLeave(人事部門);
}else {
    otherOp();
}

那麼用職責鏈模式來實現場景功能:

先定義一個Handler類(將來每個角色的父類):

注意:這裡的成員變數的許可權修飾要控制protected,否則子類沒辦法繼承的到,特別是針對Handler successor; 就是讓這個以後有種"套娃

"呼叫的感覺來實現呢! 看下去你會懂得5分鐘就ok  ..5分鐘你學不來吃虧5分鐘你看不了上當!

public abstract class Handler {

    protected String name;

    protected Handler successor;



    public Handler(String name) {
        this.name = name;
    }

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void handleRequest(Client request);

}

再建立Client基類:

public class Client {

    private String leaveName;
    private int leaveDays;

    public Client(String leaveName, int leaveDays) {
        this.leaveName = leaveName;
        this.leaveDays = leaveDays;
    }
  //getter 和 setter 省略要不看著眼花
}

再建立對應的角色類,並繼承Handler及實現物件的抽象方法:

1.組長:

public class GroupLeader extends Handler {

    public GroupLeader(String name) {
        super(name);
    }

    public void handleRequest(Client request) {
        if (request.getLeaveDays() <= 1) {
            System.out.println("組長:" + name + "  審批員工  " + request.getLeaveName()
                    + "  的請假條,請假天數為 " + request.getLeaveDays() + " 天。");
        } else {
            if (this.successor != null) {//我幹不了,下一個人!走你!
                this.successor.handleRequest(request);
            }else{//我幹不了....但是後面沒人了
                System.out.println("組長:" + name + "認為員工  "
                        + request.getLeaveName() + "  專案進展慢,不允許請假");
            }
        }
    }

2.經理:

public class Manager extends Handler {

    public Manager(String name) {
        super(name);
    }

    public void handleRequest(Client request) {
        if (request.getLeaveDays() <= 3) {
            System.out.println("經理:" + name + "  審批員工  " + request.getLeaveName()
                    + "  的請假條,請假天數為 " + request.getLeaveDays() + " 天。");
        } else {
            if (this.successor != null) {//我幹不了,下一個人!走你!
                this.successor.handleRequest(request);
            }else{//我幹不了....但是後面沒人了
                System.out.println("經理:" + name + "認為員工  "
                        + request.getLeaveName() + "  專案進展慢,不允許請假");
            }
        }
    }

}

3.人事部門

public class HRDepartment extends Handler {

    public HRDepartment(String name) {
        super(name);
    }

    public void handleRequest(Client request) {
        if (request.getLeaveDays() <= 7) {
            System.out.println("HR:" + name + "  審批員工  " + request.getLeaveName()
                    + "  的請假條,請假天數為 " + request.getLeaveDays() + " 天。");
        } else {
            if (this.successor != null) {//我幹不了,下一個人!走你!
                this.successor.handleRequest(request);
            }else{//我幹不了....但是後面沒人了
                System.out.println("HR:" + name + "認為員工  "
                        + request.getLeaveName() + "  專案進展慢,不允許請假");
            }
        }
    }
    
}

最後看看主函式:

public static void main(String args[])  {

        Handler groupLeader,hr,manager;

        groupLeader = new GroupLeader("王明");
        manager = new Manager("趙強");
        hr = new HRDepartment("李波");

        groupLeader.setSuccessor(manager); // 排傳遞順序構造職責鏈,主要的也是體現在這上的建立和以後的應用
        manager.setSuccessor(hr);


        Client lr1 = new Client("張三", 1);
        groupLeader.handleRequest(lr1);

        Client lr2 = new Client("李四", 2);
        groupLeader.handleRequest(lr2);

        Client lr3 = new Client("王五", 5);
        groupLeader.handleRequest(lr3);

        Client lr4 = new Client("趙六", 10);
        groupLeader.handleRequest(lr4);


    }

結果:

    //組長:王明  審批員工  張三  的請假條,請假天數為 1 天。
    //經理:趙強  審批員工  李四  的請假條,請假天數為 2 天。
    //HR:李波  審批員工  王五  的請假條,請假天數為 5 天。
    //HR:李波認為員工  趙六  專案進展慢,不允許請假

慢慢品味你就會發現簡單的技術大大的思維了;

如果你還沒看見職責鏈的特點,那麼我們試著註釋點東西;


請忽略這個原諒綠的顏sai- -!

這兩行註釋掉會怎麼樣呢?

結果:

//組長:王明  審批員工  張三  的請假條,請假天數為 1 天。
//經理:趙強  審批員工  李四  的請假條,請假天數為 2 天。
//經理:趙強認為員工  王五  專案進展慢,不允許請假
//經理:趙強認為員工  趙六  專案進展慢,不允許請假

我們會發現職責鏈的尾巴變成了經理那麼對應的天數上線變成了5天,從而職責鏈的執行起來也很是有的 (這也體現了職責鏈的耦合性很好,隨時隨節點新增修改,這只是簡單的 out.print列印  如果是複雜的邏輯體現的就更大了)


咳咳!重點重點!


小山已經用白話點破了職責鏈,那麼系統化的特點還是要指出的.

一.說明:

避免請求傳送者與接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連線成一條鏈,並且沿著這條鏈傳遞請求,直到有物件處理它為止。

  1. 客戶端傳送一個請求,有多個物件都有機會來處理這個請求,但客戶端不知道究竟誰來處理。
  2. 客戶端只知道他提交請求的第一個物件,從第一個物件開始處理,整個職責鏈中的物件要麼處理請求,要麼轉發給下一個接受者。
  3. 在標準的職責鏈模式中,只要有物件處理了請求,這個請求就到此為止,不再被傳遞和處理了。
  4. 在職責鏈模式中,請求不一定會被處理,因為可能沒有合適的處理者。請求在職責鏈中從頭到尾,每個處理物件都判斷不屬於自己處理,最後請求就沒有物件來處理。

在實際開發中,經常會遇到把職責鏈稍稍變形的用法。一個請求在職責鏈中傳遞,每個物件處理完後不是停止,而是繼續向下傳遞請求,當請求通過所有物件處理後,功能也就處理完成了,這樣的職責鏈稱為功能鏈。


二.缺點:

1.請求者和接收者鬆耦合
在職責鏈模式中,請求者並不知道接收者是誰,也不知道具體如何處理,請求者只是負責向職責鏈傳送請求就可以了(面向物件嘍)。而每個職責物件也不用管請求者或者是其他的職責物件,只負責處理自己的部分(單職責部分),其他的就交給其他的職責物件去處理。也就是說,請求者和接受者是完全解耦的。

2.動態組合職責
職責鏈模式會把功能處理分散到單獨的職責物件中,然後再使用的時候,可以動態組合職責形成職責鏈,從而可以靈活地給物件分配職責,也可以靈活地實現和改變物件的職責。

3.產生很多細粒度物件
職責鏈模式會把功能處理分散到單獨的職責物件中,也就是每個職責物件只處理一個方面的功能,要把整個業務處理完,需要很多職責物件的組合,這樣會產生大量的細粒度職責物件。組長處理不掉的會傳遞給下層責任鏈經理那(如果有下層),那麼本身組長的責任層已經建立,只是對應的判斷沒有進去,那麼對於組長本身只是起到了傳遞資訊的作用,但職責鏈模式卻建立並佔用了記憶體,可以變相的看成"無效"佔用。

4.不一定能被處理
職責鏈模式的每個職責物件只負責自己處理的那一部分,因此可能會出現某個請求把整個鏈傳遞完了都沒有職責物件處理它。這就需要使用職責鏈模式的時候,需要提供預設的處理,並且注意構造的鏈的有效性。


臨時叫去評審先寫到這