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