C++設(shè)計模式之職責(zé)鏈模式
前言
最近心情很差,因為生活,因為工作;所以想請幾天假去麗江玩玩。就向項目經(jīng)理提交了休假申請,我的項目經(jīng)理向項目主管提交了我的休假申請,項目主管向部門經(jīng)理提交了我的休假申請;最后,部門經(jīng)理同意了我的休假申請。是的,一個簡單的休假申請,需要這么復(fù)雜的流程,這也是一個公司保證它正常運行的必要。如果部門經(jīng)理休假了,那么我的休假申請由誰審批呢?這個時候由項目主管代替部門經(jīng)理進行審批。一個休假申請的審批制度有著嚴格的要求。而在處理這個請假審批時,各個人員就好比在一條鏈上的節(jié)點,我不知道我的請求由誰審批,但是,我的請求最終會有人來處理的。而這樣的一種行為,就好比我今天需要總結(jié)的職責(zé)鏈模式一樣。
什么是職責(zé)鏈模式?
在GOF的《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書中對職責(zé)鏈模式是這樣說的:使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對象連成一條鏈,直到有一個對象處理它為止;如下圖:
對于每個角色,他們都有他們的職責(zé);當我提交了休假申請時,項目經(jīng)理需要判斷,看看自己能否處理,如果休假超過了2個小時,那么項目經(jīng)理就不能處理了;項目經(jīng)理將這個請求提交到項目主管,項目主管判斷部門經(jīng)理在不在,如果部門經(jīng)理在,項目主管就不能處理了;最后,我的休假申請就到了部門經(jīng)理那里了,由他親自審批??梢院苊黠@的看到,項目經(jīng)理、項目主管和部門經(jīng)理都有可能處理我的休假申請,我的請求沿著這條鏈一直走下去,直到有人處理了我的請求。
UML類圖
Handler:定義了一個處理請求的接口;其它類如果需要處理相同的請求,可以實現(xiàn)該接口就好了;
ConcreteHandler:處理它所負責(zé)的請求,如果可處理該請求,就處理掉這個請求;否則將該請求轉(zhuǎn)發(fā)給它的下一個可以處理該請求的對象,所以它必須能訪問它的下一個可以處理同樣請求的對象;
Client:向處理對象提出具體的請求。
當客戶提交一個請求時,請求沿著一條鏈傳遞,直至有一個ConcreteHandler對象負責(zé)處理它。
使用場合
1.有多個的對象可以處理一個請求,由哪個對象處理該請求是在運行時刻自動確定的;
2.如果想在不明確指定接收者的情況下,向多個對象中的一個提交一個請求;
3.可以處理一個請求的對象集合應(yīng)被動態(tài)指定。
代碼實現(xiàn)
#include <iostream>
using namespace std;
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
class HolidayRequest
{
public:
HolidayRequest(int hour) : m_iHour(hour){}
int GetHour() { return m_iHour; }
private:
int m_iHour;
};
// The holiday request handler interface
class Manager
{
public:
virtual bool HandleRequest(HolidayRequest *pRequest) = 0;
};
// Project manager
class PM : public Manager
{
public:
PM(Manager *handler) : m_pHandler(handler){}
bool HandleRequest(HolidayRequest *pRequest)
{
if (pRequest->GetHour() <= 2 || m_pHandler == NULL)
{
cout<<"PM said:OK."<<endl;
return true;
}
return m_pHandler->HandleRequest(pRequest);
}
private:
Manager *m_pHandler;
};
// Department manager
class DM : public Manager
{
public:
DM(Manager *handler) : m_pHandler(handler){}
bool HandleRequest(HolidayRequest *pRequest)
{
cout<<"DM said:OK."<<endl;
return true;
}
// The department manager is in?
bool IsIn()
{
return true;
}
private:
Manager *m_pHandler;
};
// Project supervisor
class PS : public Manager
{
public:
PS(Manager *handler) : m_pHandler(handler){}
bool HandleRequest(HolidayRequest *pRequest)
{
DM *pDM = dynamic_cast<DM *>(m_pHandler);
if (pDM != NULL)
{
if (pDM->IsIn())
{
return pDM->HandleRequest(pRequest);
}
}
cout<<"PS said:OK."<<endl;
return true;
}
private:
Manager *m_pHandler;
};
int main()
{
DM *pDM = new DM(NULL);
PS *pPS = new PS(pDM);
PM *pPM = new PM(pPS);
HolidayRequest *pHolidayRequest = new HolidayRequest(10);
pPM->HandleRequest(pHolidayRequest);
SAFE_DELETE(pHolidayRequest);
pHolidayRequest = new HolidayRequest(2);
pPM->HandleRequest(pHolidayRequest);
SAFE_DELETE(pDM);
SAFE_DELETE(pPS);
SAFE_DELETE(pPM);
SAFE_DELETE(pHolidayRequest);
}
優(yōu)缺點
1.降低耦合度;職責(zé)鏈模式使得一個對象不用知道是哪一個對象處理它的請求。對象僅需要知道該請求會被正確的處理。接收者和發(fā)送者都沒有對方的明確的信息,且鏈中的對象不需要知道鏈的結(jié)構(gòu);
2.增強了給對象指派職責(zé)的靈活性;當在對象中分派職責(zé)時,職責(zé)鏈給你更多的靈活性。你可以通過在運行時對該鏈進行動態(tài)的增加或修改來增加或改變處理一個請求的那些職責(zé);
3.不保證被接受,既然一個請求沒有明確的接收者,那么就不能保證它一定會被處理;該請求可能一直到鏈的末端都得不到處理。一個請求也可能因該鏈沒有被正確配置而得不到處理。
總結(jié)
職責(zé)鏈模式在實現(xiàn)時,需要處理好它的后繼者的問題,就是說,如果我不處理這個請求,那么我將把這個請求發(fā)給誰去處理呢?同時,職責(zé)鏈模式在實現(xiàn)時,它的鏈的形狀并不是由職責(zé)鏈本身建立和維護的,而是由客戶進行創(chuàng)建的,由客戶指定每一個處理者的后繼者是誰。這就大大的提高了職責(zé)鏈的靈活性。在實際中,我們也可以將職責(zé)鏈模式與組合模式相結(jié)合,一個構(gòu)件的父構(gòu)件可以作為它的后繼者。
上一篇:C++中的類型轉(zhuǎn)換static_cast、dynamic_cast、const_cast和reinterpret_cas
欄 目:C語言
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/3308.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
 - 01-10深入理解C++中常見的關(guān)鍵字含義
 - 01-10使用C++實現(xiàn)全排列算法的方法詳解
 - 01-10APUE筆記之:進程環(huán)境詳解
 - 01-10c++中inline的用法分析
 - 01-10用C++實現(xiàn)DBSCAN聚類算法
 - 01-10全排列算法的非遞歸實現(xiàn)與遞歸實現(xiàn)的方法(C++)
 - 01-10C++大數(shù)模板(推薦)
 - 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
 - 01-10深入C/C++浮點數(shù)在內(nèi)存中的存儲方式詳解
 


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
 - 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
 - 04-02c語言的正則匹配函數(shù) c語言正則表達
 - 04-02c語言用函數(shù)寫分段 用c語言表示分段
 - 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
 - 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
 - 04-02c語言沒有round函數(shù) round c語言
 - 04-02c語言分段函數(shù)怎么求 用c語言求分段
 - 04-02C語言中怎么打出三角函數(shù) c語言中怎
 - 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
 
隨機閱讀
- 01-10C#中split用法實例總結(jié)
 - 01-10delphi制作wav文件的方法
 - 08-05DEDE織夢data目錄下的sessions文件夾有什
 - 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
 - 08-05織夢dedecms什么時候用欄目交叉功能?
 - 04-02jquery與jsp,用jquery
 - 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
 - 01-10使用C語言求解撲克牌的順子及n個骰子
 - 01-11ajax實現(xiàn)頁面的局部加載
 - 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
 


