責任鏈模式(Chain of Responsibility Pattern)為請求創建一個接受者對象的鏈。這種模式給與請求的類型,對請求的發送者和接受者進行解耦。屬於行為型模式。
在這種模式中,通常每個接收者都包含對另一個接收者的引用。如果一個對象不能處理該請求,那麼它會把相同的請求傳給下一個接收者,依此類推。
意圖
避免請求發送者和接受者耦合在一起,讓多個對象都有可能接收請求,將這些對象連接成一條鏈,並且沿著這條連傳遞請求,直到有對象處理它為止。
主要解決
職責鏈上的處理者負責處理請求,客戶只需要將請求發送到職責鏈上即可,無須關心請求的處理細節和請求的傳遞,所以職責鏈將請求的發送者和請求的處理者解耦了。
如何解決
攔截的類都統一實現接口
優點
1. 降低耦合度,它將請求的發送者和接受者解耦
2. 簡化了對象,使得對象不需要知道鏈的結構
3.增強給對象指派職責的靈活性。通過改變鏈內的成員或者調用他們的次序,允許動態新增或刪除責任
4. 增加新的請求處理很方便
缺點
1. 不能保證請求一定會被接收;
2. 系統性能將受到一定的影響,而且在進行代碼調試時不太方便,可能造成循環調用
3. 可能不容易觀察運行時的 特徵,有礙於出錯
使用場景
1. 有多個對象可以處理同一個請求,具體哪個對象處理請求由運行時刻自動確定。
2. 在不明確指定接受者的 情況下,向多個對象中的一個提交一個請求。
3. 可動態指定一組對象處理請求
UML類圖:
C++實現
舉個例子:
以後上班的我想要請假這個流程是這樣的:首先我得向項目經理提交休假申請;我的項目經理 向 項目主管提交了我的休假申請,項目主管 向 部門經理提交我的休假申請;最後,部門經理同意了我的休假申請。那麼如果部門經理休假了,這個申請由誰來審批呢?這個時候就會交給項目主管進行審批。是挺麻煩的,但也是公司正常運行的必要。 在處理這個請假審批時,各個人員就好比在一條鏈上的節點,我不知道我的請求由誰審批,但是,我的請求最終會有人來處理的。這就是我想要實現的責任鏈模式。
解釋: 對於每個角色,他們都有他們的職責;當我提交了休假申請時,項目經理需要判斷,看看自己能否處理,如果休假超過了2個小時,那麼項目經理就不能處理了;項目經理將這個請求提交到項目主管,項目主管判斷部門經理在不在,如果部門經理在,項目主管就不能處理了;最後,我的休假申請就到了部門經理那裡了,由他親自審批。可以很明顯的看到,項目經理、項目主管和部門經理都有可能處理我的休假申請,我的請求沿著這條鏈一直走下去,直到有人處理了我的請求。
code :
[cpp] view plain copy
//責任鏈模式
class HolidayRequest
{
public:
HolidayRequest(int hour)
:m_iHour(hour)
{}
int GetHour()
{
return m_iHour;
}
private:
int m_iHour;
};
class Manager
{
public:
virtualbool HandleRequest(HolidayRequest* request) = 0;
};
class PM : public Manager //PM:Project manager項目經理
{
public:
PM(Manager* handler)
:m_Handler(handler)
{}
bool HandleRequest(HolidayRequest* request)
{
if (request->GetHour() <= 2 || m_Handler == NULL)
{
cout << "PM said : OK" << endl;
returntrue;
}
return m_Handler->HandleRequest(request);
}
private:
Manager* m_Handler;
};
class DM : public Manager //DM:Department Manager部門經理
{
public:
DM(Manager* handler)
-
:m_handler(handler)
{}
bool HandleRequest(HolidayRequest* request)
{
cout <
returntrue;
}
bool IsIn()
{
returntrue;
}
private:
Manager *m_handler;
};
class PS : public Manager //Project Supervisor部門主管
{
public:
PS(Manager* handler)
:m_handler(handler)
{}
bool HandleRequest(HolidayRequest* request)
{
DM* pDM = dynamic_cast
(m_handler); if (pDM != NULL)
{
if (pDM->IsIn())
return pDM->HandleRequest(request);
}
cout <
returntrue;
}
private:
Manager* m_handler;
};
客戶端:
[cpp] view plain copy
int tets_chain_of_Responsibility_Pattern() //責任鏈模式
{
DM* pDM = new DM(NULL);//部門經理
PS* pPS= new PS(pDM);//部門主管
PM* pPM = new PM(pPS);//項目經理
HolidayRequest* Prequest = new HolidayRequest(10);
pPM->HandleRequest(Prequest);
delete Prequest;
Prequest = new HolidayRequest(2);
pPM->HandleRequest(Prequest);
delete pDM;
delete pPS;
delete pPM;
delete Prequest;
system("pause");
return 0;
}
總結
責任鏈模式的實現時,需要處理好它的後繼者問題,也就是說,如果我不處理這個請求,那麼我將把這個請求發給誰去處理呢?同時,責任鏈模式在實現時,它的鏈的形狀不是職責鏈本身建立和維護的,而是由客戶進行創建的,這就大大提高了責任鏈的靈活性。
閱讀更多 青峰科技 的文章