設計模式介紹之八:職責鏈模式(Chain of responsibility)

設計模式介紹之八:職責鏈模式(Chain of responsibility)

    職責鏈模式使得一個軟體系統中的多個物件都有機會處理請求,將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它為止,從而避免請求的傳送者和接收者之間產生強耦合關係。

    常見的應用程式框架中有很多職責鏈模式的應用,比如 MFC 中的訊息處理機制、 Android 中的按鍵處理流程、Qt 中的事件處理機制等等。

    下圖是職責鏈模式的 UML 圖示:

    這裡舉一個簡單的示例。是這樣的,某個家庭有一個小菇涼,有爸爸、媽媽、奶奶,小菇涼想要吃巧克力,就挨個問,直到有人同意就開吃。

    標頭檔案:    

class Child {
Child();
void eatChocolate();
void setHandler(Handler *handler);
private:
Handler * m_pHandler;
};
class Handler {
Handler();
virtual ~Handler();
virtual bool canIEatChocolate() = 0;
void setSuccessor(Handler * handler){ m_pSuccessor = handler;}
Handler * successor(){ return m_pSuccessor;}
private:
Handler * m_pSuccessor;
};
class Mother : public Handler{
bool canIEatChocolate();
};
class Father : public Handler{
bool canIEatChocolate();
};
class Grandmother : public Handler{
bool canIEatChocolate();
};

    原始檔(這裡設定爸爸、媽媽都不讓吃,奶奶讓吃):

Child::Child():m_handler(0)
{}
void Child::eatChocolate(){
if(m_pHandler->canIEatChocolate()){
laughThenEat();
}else{
cry();
}
}
void Child::setHandler(Handler * handler){
m_pHandler = handler;
}
Handler::Handler():m_pSuccessor(0){
}
bool Mother::canIEatChocolate(){
if(successor()){
return successor->canIEatChocolate();
}else{
return false;
}
}
bool Father::canIEatChocolate(){
if(successor()){
return successor->canIEatChocolate();
}else{
return false;
}
}
bool Grandmother::canIEatChocolate(){
if(successor()){
return successor->canIEatChocolate();
}else{
return true;
}
}

    驅動程式碼, main() 函式:

int main(int argc, char**argv)
{
Child * child = new Child;
Mother * mother = new Mother;
Father * father = new Father;
Grandmother * grandmother = new Grandmother;
mother->setSuccessor(father);
father->setSuccessor(grandmother);
child->setHandler(mother);
child->eatChocolate();
return 0;
}

    好啦,以上就是職責鏈模式的一個簡單實現。這裡手動建立了一個連結串列,將連結串列頭指標設定給 Child 。另一個更常用的做法,是在 Child 內部維護一個連結串列,在Child::eatChocolate() 函式內部使用迴圈遍歷連結串列,遇到 canIEatChocolate() 返回 true 就停止,這裡不再贅述了。

    回顧一哈: