1. 程式人生 > >行為型設計模式之責任鏈模式

行為型設計模式之責任鏈模式

責任鏈模式介紹

責任鏈模式是一種鏈式結構,就是由一個個節點首尾相接串起來的結構,具有很好的靈活性,將每一個節點看作是一個物件,每一個物件擁有不同的處理邏輯,將一個請求從鏈式的首端發出,沿著鏈的路徑依此傳遞每一個節點物件,直到有物件處理這個請求為止,我們將這樣一種模式稱為責任鏈模式。

責任鏈模式的定義

使多個物件都有機會處理請求,從而避免了請求的傳送者和接受者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。

責任鏈模式的使用場景

(1)多個物件可以處理同一請求,但具體哪個物件處理則是在執行時動態決定

(2)在請求者不明確的情況下向多個物件中的一個提交一個請求

(3)需要動態指定一組物件的處理請求

責任鏈模式的類圖

角色介紹:

  • AbstractHandler - 抽象處理者角色,宣告一個請求處理的方法(handle())、一個獲得處理級別的方法(getHandlerLever())和封裝了一個對具體的處理轉發邏輯實現的方法(handleRequest()),並在其中保持對下一個處理節點的AbstractHandler物件的引用(nextHandler)
  • ConcreteHandler1、2 - 具體處理者角色,對請求進行處理,如果不能處理就將請求轉發給下一個節點上的處理物件
  • AbstractRequest - 抽象的請求類,裡面聲明瞭一個獲得請求內容的方法(getContent())和一個獲得請求處理級別的方法(getRequestLever())
  • ConcreteRequest - 具體的請求類

責任鏈模式的簡單實現

在一個公司中,員工拿到了一份合同,需要上級的簽名,於是員工就把合同給組長,但是組長沒有許可權簽名,於是組長就把合同給經理,但是經理也沒有足夠的許可權簽名,於是經理就把合同給老闆,老闆二話不說就把合同給簽了。上面的例子就是責任鏈模式,員工是請求的發起者,處於鏈的底端,而老闆是處於鏈條頂端的類,員工發起請求後,請求經過層層轉發,直至請求被處理,員工只是和組長髮生了關聯,後面合同被誰處理,員工並不知道,也並不關心,他在乎的是合同簽名的結果,責任鏈模式很好的將請求的發起者與處理者解耦,下面用程式碼來模擬。

抽象的員工,即AbstractHandler角色

public abstract class Staff {

    protected Staff nextHandler;//上一級領導處理者

    //處理轉發的邏輯
    public final void handleRequest(Contract contract){
        if(contract.getContractLever() < getHandlerLever()){
            handle(contract);
        }else {
            if(nextHandler != null){
                nextHandler.handleRequest(contract);
            }
        }
    }

    public abstract int getHandlerLever();//自身能處理請求的級別
    public abstract void handle(Contract contract);//具體的處理過程
}

在這個抽象的處理者中,一是定義了兩個介面來確定一個Staff應有的行為和屬性,二是封裝了一個處理請求的邏輯轉發方法,確定當前Staff是否有足夠的級別來處理當前合同,如果沒有,就把合同轉發給上一級Staff,接下來是各個實現類。

組長,即ConcreteHandler角色

public class CroupStaff extends Staff {

    @Override
    public int getHandlerLever() {
        return 1;
    }

    @Override
    public void handle(Contract contract) {
        System.out.println("組長簽名了合同!");
    }

}

經理,即ConcreteHandler角色

public class ManagerStaff extends Staff {
    @Override
    public int getHandlerLever() {
        return 2;
    }

    @Override
    public void handle(Contract contract) {
        System.out.println("經理簽名了合同!");
    }
}

老闆,即ConcreteHandler角色

public class BossStaff extends Staff {
    @Override
    public int getHandlerLever() {
        return 3;
    }

    @Override
    public void handle(Contract contract) {
        System.out.println("老闆簽名了合同!");
    }
}

 接下來看一看請求,就是合同

抽象的合同類,即AbstractRequest角色

public abstract class Contract {
    public abstract String getContext();//獲得合同具體內容
    public abstract int getContractLever();//獲得合同處理級別
}

具體的合同類,即ConcreteRequest角色

public class ConcreteContract extends Contract {

    @Override
    public String getContext() {
        return "這是一份關於房產合作的合同";
    }

    @Override
    public int getContractLever() {
        return 3;
    }
}

 最後員工從組長髮起請求

請求發起者,員工

public class Employee {

    public static void main(String[] args){
        //構造各個節點物件
        GroupStaff groupStaff = new GroupStaff();
        ManagerStaff managerStaff = new ManagerStaff();
        BossStaff bossStaff = new BossStaff();
        //構成一條鏈
        groupStaff.nextHandler = managerStaff;
        managerStaff.nextHandler = bossStaff;
        //發起請求
        Contract contract = new ConcreteContract();
        groupStaff.handleRequest(contract);
    }

}
輸出結果
老闆簽名了合同!

 其實這裡也可以直接繞過組長和經理,直接找老闆簽名,這也是責任鏈模式的靈活性,請求的發起可以從任意節點發起,同時也可以改變責任鏈模式內部的傳遞規則,如直接找老闆簽名。

總結

對於責任鏈模式中的節點,有兩個行為,一是處理請求,二是將請求轉發給下一個節點,不允許某個節點處理者處理了請求後又把節點轉發給下一個節點。對於責任鏈中的請求,只有倆個結果,一個是被某個節點處理,一個是所有物件均沒有處理。

優點:

請求者和處理者關係解耦

缺點:

對鏈中節點的遍歷,如果節點太多,會影響效能