設計模式之對象行爲型模式 — CHAIN OF RESPONSIBILITY (職責鏈)模式

意圖

使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關係。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理他爲止。

示例代碼

//test.h 文件  

#pragma once

#include <iostream>
using namespace std;

typedef int Topic;
const Topic NO_HELP_TOPIC = -1;

class HelpHandler
{
public:
    //@successor    後繼者  
    //@topic        主題
    HelpHandler(HelpHandler* successor = NULL, Topic topic = NO_HELP_TOPIC);
    virtual bool HasHelp();     //是否有幫助信息   
    virtual void SetHandler(HelpHandler * successor, Topic topic);
    virtual void HandleHelp();
private:
    HelpHandler *m_successor;   //後繼者
    Topic m_topic;
};

// 所有的窗口組件都是Widget 抽象類的子類  
// Widget是Helphandler 的子類,所有的窗口組件都有幫助文檔
class Widget:public HelpHandler
{
public:
    //@parent 父窗口 也是 職責鏈中的 後繼者 
    Widget(Widget *parent, Topic topic = NO_HELP_TOPIC);
protected:
private:
    Widget *m_parent;
};

class Button:public Widget
{
public:
    Button(Widget *parent, Topic topic = NO_HELP_TOPIC);
    virtual void HandleHelp();
protected:
private:

};

//Dialog的後繼者不是窗口組件,而是任意的幫助請求處理對象。
//在我們這個應用中這個後繼者將是Application的一個實例

class Dialog :public Widget
{
public:
    Dialog(HelpHandler * successor,Topic topic=NO_HELP_TOPIC);
    virtual void HandleHelp();
protected:
private:
};

//鏈的末端是Application的一個實例,該應用不是一個窗口組件。當幫助請求
//傳到這一層時,該應用可提供一般的信息

class Application :public HelpHandler
{
public:
    Application(Topic topic);
    virtual void HandleHelp();
protected:
private:
};

//test.cpp  文件 
#include "test.h"

HelpHandler::HelpHandler(HelpHandler* successor /*=0*/, Topic topic/*=NO_HELP_TOPIC*/)
:m_successor(successor), m_topic(topic)
{

}

bool HelpHandler::HasHelp()
{
    return m_topic != NO_HELP_TOPIC;
}

void HelpHandler::SetHandler(HelpHandler * successor, Topic topic)
{
    m_topic = topic;
    m_successor = successor;
}

void HelpHandler::HandleHelp()
{
    if (m_successor != NULL)   //如果有後繼者,則把請求傳遞給後繼者
    {
        m_successor->HandleHelp();
    }
}

/************************************************************************/



Widget::Widget(Widget *parent, Topic topic /*= NO_HELP_TOPIC*/)
:HelpHandler(parent,topic)
{
    m_parent = parent;
}

/******************************************************************/
Button::Button(Widget *parent, Topic topic /*= NO_HELP_TOPIC*/)
:Widget(parent,topic)
{

}

void Button::HandleHelp()
{
    if (HasHelp())   //如果有幫助文檔,則顯示;如果沒有,則傳遞到他的父類 即他的後繼者
    {
        cout << "按鈕幫助文檔\n" << endl;
    }
    else
    {
        HelpHandler::HandleHelp();    
    }
}

Dialog::Dialog(HelpHandler * successor, Topic topic/*=NO_HELP_TOPIC*/)
:Widget(0)   //後繼者並不是Widget  
{
    SetHandler(successor, topic);
}

void Dialog::HandleHelp()
{
    //如果有幫助文檔,則顯示;如果沒有,則傳遞到他的父類 即他的後繼者
    if (HasHelp())
    {
        cout << "Dialog 的幫助文檔  \n" << endl;
    }
    else
    {
        HelpHandler::HandleHelp();
    }
}


/**********************************************************/

Application::Application(Topic topic)
:HelpHandler(0,topic)    //沒有後繼者   
{

}

void Application::HandleHelp()
{
    cout << "幫助目錄\n 1. 按鈕幫助\n2. 窗口幫助 \n" << endl;
}


---------------------------------------

//main.cpp

#include "test.h"

int main()
{
    const Topic ONE_TOPIC = 1;
    const Topic TOW_TOPIC = 2;
    const Topic THREE_TOPIC = 3;

    Application *app = new Application(ONE_TOPIC);
    Dialog *dialog = new Dialog(app, TOW_TOPIC);
    Button *button = new Button(dialog,NO_HELP_TOPIC);

    button->HandleHelp();

    getchar();
    return 0;
}

思路:

app是dialog的後繼者 ; dialog 是button的後繼者;

button幫助消息的傳遞路徑:
button ->dialog->app
button 的topic = NO_HELP_TOPIC 即沒有幫助 所以向 dialog傳遞 。


表示請求

表示請求可以不用像示例代碼一樣 直接寫成 HandleHelp( ); 可以使用處理函數來處理更多的請求

代碼框架

virtual void HandleRequest(Request * request)
    {
        switch (request->GetKind())
        {
        case Help:
            /* .........  */
            break;
        case Print:
            /*............*/
            break;
        default:
            break;
        }
    }

效果

  • 減低耦合度
  • 增強了給對象指派職責的靈活性
  • 不保證被接受

我的個人網站 http://www.breeziness.cn/
我的CSDN http://blog.csdn.net/qq_33775402

轉載請註明出處 小風code www.breeziness.cn

發佈了78 篇原創文章 · 獲贊 75 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章