聲明:本系列文章主要參考《精通Python設計模式》一書,並且參考一些資料,結合自己的一些看法來總結而來。
之前在最開始就聊了Python設計模式有三種,其中關於創建型和結構型設計模式基本都已經聊了,那么現在來聊聊關於Python設計模式的 行為型設計模式 。
行為型設計模式:
用來處理系統實體之間通信的設計模式。
接下來,聊一下關於行為型設計模式的第一種 -- 責任鏈模式。
責任鏈模式
根據《精通Python設計模式》書中介紹如下:
責任鏈模式 -- 用於讓多個對象處理一個請求時,或者用於預先不知道由哪個對象來處理某種特定請求時,其原則如下:
1、存在一個對象鏈(鏈表、樹或者其他便捷的數據結構)。
2、一開始將請求發送給第一個對象,讓其處理。
3、對象決定是否處理該請求。
4、對象將請求轉發給下一個對象。
5、重復該過程,直到達到鏈尾。
可能看概念介紹還會很模糊,那么接下來看一下需求吧。
需求
假設有這么一個請假系統:員工若想要請3天以內(包括3天的假),只需要直屬經理批准就可以了;如果想請3-7天,不僅需要直屬經理批准,部門經理需要最終批准;如果請假大於7天,不光要前兩個經理批准,也需要總經理最終批准。類似的系統相信大家都遇到過,那么該如何實現呢?首先想到的當然是if…else…,但一旦遇到需求變動,其臃腫的代碼和復雜的耦合缺點都顯現出來。簡單分析下需求,“假條”在三個經理間是單向傳遞關系,像一條鏈條一樣,因而,我們可以用一條“鏈”把他們進行有序連接。
示例:
class Manager(): """經理類""" successor = None name = '' def __init__(self, name): self.name = name def setSuccessor(self, successor): # 設置上級 self.successor = successor def handleRequest(self, request): # 處理請求 pass class LineManager(Manager): '''直屬經理''' def handleRequest(self, request): if request.requestType == 'DaysOff' and request.number <= 3: return '%s:%s Num:%d Accepted OVER' % (self.name, request.requestContent, request.number) else: return '%s:%s Num:%d Accepted CONTINUE' % (self.name, request.requestContent, request.number) if self.successor != None: self.successor.handleRequest(request) class DepartmentManager(Manager): '''部門經理''' def handleRequest(self, request): if request.requestType == 'DaysOff' and request.number <= 7: return '%s:%s Num:%d Accepted OVER' % (self.name, request.requestContent, request.number) else: return '%s:%s Num:%d Accepted CONTINUE' % (self.name, request.requestContent, request.number) if self.successor != None: self.successor.handleRequest(request) class GeneralManager(Manager): '''總經理''' def handleRequest(self, request): if request.requestType == 'DaysOff': return '%s:%s Num:%d Accepted OVER' % (self.name, request.requestContent, request.number) class Request(): def __init__(self, requestType ,requestContent, number = 0): self.requestType = requestType self.requestContent = requestContent self.number = number def commit(self,generalManager): ret = generalManager.handleRequest(self) print(ret) return ret
分析:
1、有一個Request類,用來構建請求,同時調用commit方法提高到責任鏈的首段即 lineManager對象 來處理。
2、lineManager在處理該請求時,去校驗是否為 請假類型和請假天數,若為請求天數 > 3天,則判斷是否有上級,若有則調用上級即 departManager對象來處理。
3、部門領導如上,若請求天數 > 7天則提交給總經理 generalManager來處理,直到責任鏈的尾端。
4、責任鏈處理到尾端,則返回處理結果,當然該示例中沒有結果返回。
使用:
if __name__=="__main__": line_manager = LineManager('LINE MANAGER') department_manager = DepartmentManager('DEPARTMENT MANAGER') general_manager = GeneralManager('GENERAL MANAGER') line_manager.setSuccessor(department_manager) department_manager.setSuccessor(general_manager) request = Request(requestContent="'Ask 1 day off'", requestType='DaysOff', number=1) request.commit(line_manager) request = Request(requestContent="'Ask 5 day off'", requestType='DaysOff', number=5) request.commit(line_manager) request = Request(requestContent="'Ask 10 day off'", requestType='DaysOff', number=10) request.commit(line_manager)
上述代碼案例:用編程專業術語來說是一個單向鏈表,若 經理也可以發布任務,給其下級,其下級處理了再發給下下級~~,以此類推,則 可以實現一個雙向鏈表。
這種鏈表組織:可以解耦發送方 和接收方。即 請求只需發送給 直屬經理即可。而下方任務,只需發送給部門經理即可。
該模式的優缺點:
優點:
1、將請求者與處理者分離,請求者並不知道請求是被哪個處理者所處理,易於擴展。
缺點:
1、如果責任鏈比較長,會有比較大的性能問題;
2、如果責任鏈比較長,若業務出現問題,比較難定位是哪個處理者的問題。
應用場景:
2、若一個請求可能由一個對請求有鏈式優先級的處理群所處理時,可以考慮責任鏈模式。除本例外,銀行的客戶請求處理系統也可以用責任鏈模式實現(VIP客戶和普通用戶處理方式當然會有不同)。
over~~~
