職責鏈初步理解及應用小demo
什麼是職責鏈
先看個需要用到職責的場景:
if(請假天數 <= 1){
askForLeave(小組長);
}else if(請假天數 <= 3 && 請假天數 > 1){
askForLeave(專案經理);
}else if(請假天數 <= 7 && 請假天數 > 3){
askForLeave(人事部門);
}else {
otherOp();
}
那麼用職責鏈模式來實現場景功能:
先定義一個Handler類(將來每個角色的父類):
注意:這裡的成員變數的許可權修飾要控制protected,否則子類沒辦法繼承的到,特別是針對Handler successor; 就是讓這個以後有種"套娃
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.不一定能被處理
職責鏈模式的每個職責物件只負責自己處理的那一部分,因此可能會出現某個請求把整個鏈傳遞完了都沒有職責物件處理它。這就需要使用職責鏈模式的時候,需要提供預設的處理,並且注意構造的鏈的有效性。
臨時叫去評審先寫到這