責任鏈的目的是通過特定的設計對請求者和接收者之間進行解耦,請求者調用操作的對象,接收者接收請求并執行相關操作,通過解耦請求者不需要關心接收者的接口,同時也可增強職責的靈活性,通過改變鏈內的成員或調用次序,允許動態新增或刪除責任。
作用
責任鏈模式通過將多個對象連成鏈式模式,并沿著這個鏈傳遞命令或者請求,直到有對象處理它為止。
類視圖
實現
我們還是取比較經典的員工請假的例子。員工為請假的請求者,接收者分別從項目經理、部門經理、公司經理這幾個層級,員工向上進行請假操作,首先傳遞給項目經理,項目經理在處理時分為兩種情況,如果項目經理人在公司,并且員工的請假天數滿足請假的審批權限范圍,則給予審批,反之則申請上級進行處理。
責任鏈模式應用場景?當然我們也可以制定自己的特殊規則,比如經理級別的接收者如果人不在,就不能向上進行請求,比如開可以增加請假的事由以供經理進行判斷是否滿足請假要求等,這些都可以根據實際情況進行擴充,感興趣可以自己實現。
class DayOffRequest
{
public: DayOffRequest(int hour) :m_iHour(hour) {} int GetHour() { return m_iHour; }
private: int m_iHour;
}; class Manager
{
public: virtual bool HandleRequest(DayOffRequest* request) = 0;
}; class PM : public Manager //Project manager項目經理
{
public: PM(Manager* handler) :m_Handler(handler) {} bool HandleRequest(DayOffRequest* request) { //在權責范圍內給予批準if (request->GetHour() <= 2) { cout << "PM said : OK" << endl; return true; }else if (m_Handler) //請求上級{return m_Handler->HandleRequest(request);}else{//無法定奪cout <<"PM said :no decide" << endl; return false;}}
private: Manager* m_Handler;
}; class DM : public Manager //Department Manager部門經理
{
public: DM(Manager* handler) :m_handler(handler) {} bool HandleRequest(DayOffRequest* request) { if (m_Handler){if(request->getHour() <=16){cout <<"DM said :OK" << endl; return true;}elsereturn m_Handler->HandleRequest(request);}else{ cout <<"DM said :no decide" << endl; return false;}}
private: Manager *m_handler;
}; class GM : public Manager //General Manager 總經理
{
public: GM():m_handler(NULL) {}bool IsInCompany(){return static_cast<bool>(rand()%2) ;}bool HandleRequest(DayOffRequest* request) { if(IsInCompany()){cout <<"GM said :OK" << endl; return true;}else{cout <<"GM said :try again latter" << endl; return false;}}
private: Manager* m_handler;
};
int main()
{ Manager *general = new GM(); Manager *department = new DM(general); //設置上級 Manager *project = new PM(department); //設置上級 DayOffRequest reqsta(2); //一個員工請假2小時project->DealWithRequest(&reqsta); DayOffRequest reqstb(20); //另一個員工請假20小時project->DealWithRequest(&reqstb); delete project; delete department; delete general;
}
責任鏈和觀察者模式比較相像,都是進行命令和數據的傳遞,二者的關鍵區別是一個是有明確層級和先后關系(也可能不是那么明顯),而一個是對象平等的,最通俗的例子就是網絡中的DNS路由(鏈式)和廣播模式(群發)的實現,這下大家就明白了吧;
當然也請注意鏈式結構的效率問題,對于層級最好還是加以控制。
應用場景
- 基于鏈式的請求和應答的結構;
- 發送者并不知道在鏈中的哪個對象會響應請求;
- 責任鏈中的每一個對象都有職責絕對是否對請求進行響應