Android 責任鏈模式
Android 設計模式系列文章Android 23種設計模式
前言
責任鏈模式其實就是一種鏈式結構,比如有ABCDE這一樣一條鏈式結構,我把請求傳送給A,A接收到這個請求後,判斷是否處理,如果不處理就直接傳遞給B,同樣B如果不處理舊傳遞給C,直至傳遞到E。這種一級一級的傳遞就是鏈式結構。傳遞過程中也可以直接處理結束鏈式迴圈,比如處理到C時,處理掉請求,不會繼續傳遞到D。
責任鏈模式定義
一個請求傳送到接收者,接收者成連式結構,沿著鏈式結構傳遞請求,直到有物件處理請求。
責任鏈模式舉例
責任鏈模式定義很簡單很好理解,我們來一個例子,看看責任鏈模式的應用場景。
例子:小明需要請假15天,OA上,小明把請假遞交給組長。組長只有3天的許可權,所以組長把請假流轉給部門長處理。部門長只有7天許可權,所以請假流轉到了經理。經理經過評估,覺得可以放,於是請假批准。小東需要請假3天,組長就能批准。不會流轉到部門長那裡。
我們先寫一個員工請假類,程式碼很簡單就是請假天數
public class StaffRequestLeave { private int days; public StaffRequestLeave(int days) { this.days = days; } public final int getDays() { return days; } }
不管是組長,部門長還是經理,這些領導處理請假比較類似,所以先抽象出處理請假的領導類
import android.util.Log; abstract class Leader { static final String TAG = Leader.class.getSimpleName(); public Leader nextLeader; // 上一級領導 public final void handleLeave(StaffRequestLeave staff) { if (staff.getDays() <= getHandleLeaveDays()) { handle(staff); } else { if (nextLeader != null) { Log.d("Leader", "不處理,流轉"); nextLeader.handleLeave(staff); } else { refuseRequest(); } } } abstract int getHandleLeaveDays(); // 批准請假天數 abstract void handle(StaffRequestLeave staff); // 處理請假 abstract void refuseRequest(); // 拒絕請假 }
核心處理邏輯就在這裡,nextLeader來表示上一級領導。handleLeave統一處理請假請求。如果請假天數在許可權範圍內就批准,呼叫handle,如果超過許可權,就把請求傳送到上一級領導,如果不批准呼叫refuseRequest。
然後我們來建立組長,部門長,經理
// 組長 public class GroupLeader extends Leader { static final String TAG = GroupLeader.class.getSimpleName(); static final int permissionDay = 3; // 批准許可權天數 @Override int getHandleLeaveDays() { return permissionDay; } @Override void handle(StaffRequestLeave staff) { Log.d(TAG,TAG + " 批准放假" + staff.getDays() + "天"); } @Override void refuseRequest() { Log.d(TAG,TAG + " 拒絕放假"); } } // 部門長 public class MinisterLeader extends Leader { static final String TAG = MinisterLeader.class.getSimpleName(); static final int permissionDay = 7; // 批准許可權天數 @Override int getHandleLeaveDays() { return permissionDay; } @Override void handle(StaffRequestLeave staff) { Log.d(TAG,TAG + " 批准放假" + staff.getDays() + "天"); } @Override void refuseRequest() { Log.d(TAG,TAG + " 拒絕放假"); } } // 經理 public class ManagerLeader extends Leader{ static final String TAG = ManagerLeader.class.getSimpleName(); static final int permissionDay = 15; // 批准許可權天數 @Override int getHandleLeaveDays() { return permissionDay; } @Override void handle(StaffRequestLeave staff) { Log.d(TAG,TAG + " 批准放假" + staff.getDays() + "天"); } @Override void refuseRequest() { Log.d(TAG,TAG + " 拒絕放假"); } }
各位領導都有自己的permissionDay處理天數許可權。根據請假許可權來批准請假。
最後來看看呼叫
GroupLeader group = new GroupLeader(); MinisterLeader minister = new MinisterLeader(); ManagerLeader manager = new ManagerLeader(); group.nextLeader = minister; minister.nextLeader = manager; StaffRequestLeave xiaoMing = new StaffRequestLeave(15); StaffRequestLeave xiaoDong = new StaffRequestLeave(3); group.handleLeave(xiaoMing); group.handleLeave(xiaoDong);
列印log輸出如下:
com.yink.designpattern.designpattern D/Leader: 不處理,流轉 com.yink.designpattern.designpattern D/Leader: 不處理,流轉 11-12 08:13:53.442 3403-3403/com.yink.designpattern.designpattern D/ManagerLeader: ManagerLeader 批准放假15天 11-12 08:13:53.442 3403-3403/com.yink.designpattern.designpattern D/GroupLeader: GroupLeader 批准放假3天
1、小明請假15天,給組長髮送請求,流轉到部門長,部門長流轉到經理。批准請假。
2、小東請假3天,給組長髮送請求,直接批准。
3、當然你也可以直接越級請假。直接呼叫minister.handleLeave(xiaoMing);
責任鏈模式小結
責任鏈模式這種連式結構很好理解和記憶。
優點:請求者和處理者關係解耦,提高程式碼靈活性
缺點:對處理著遍歷,弱處理者太多,會影響效能,特別在遞迴處理中尤其需要注意。
結束語
每種設計模式都有它的有點兒於缺點。責任鏈模式也有適合它的處理場景。在Android原始碼中,責任鏈模式就被應用在View的事件分發處理。有興趣的童鞋可以去看看原始碼了。