首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

[提问] 职责链模式里参数传递有关问题

2013-01-02 
[提问] 职责链模式里参数传递问题在一个职责链模式的例子里有如下接口Handler,请讲解一下下面这段代码是如

[提问] 职责链模式里参数传递问题
在一个职责链模式的例子里有如下接口Handler,请讲解一下下面这段代码是如何工作的?参数是怎么沿着职责链传递的?

    // 这个构造函数实际就是指定后继者
    Handler(Handler *s) : _successor(s) { }



/**********************************************************************************************************\
* 作者:一雨田(http://blog.csdn.net/dylgsy/)。本文可随便转贴,但请保留此信息
*  
* Chain Of Responsibility(职责链模式)适用于:

* 1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。

* 2、你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
*
* 3、可处理一个请求的对象集合应被动态指定。 
\**********************************************************************************************************/

/**********************************************************************************************************\
* 如果客户的请求(Request)可以由好多个对象去处理,而这些对象可能组成一条链的关系,我们就可以使用职责链模式。

* 这些处理Request的类之间是一个松散的耦合,唯一共同点是在他们之间可以传递request。

* 考虑一个实例:

* 一个小孩子想吃苹果,那他会向家里面的成员请求,家里的成员包括妈妈、爸爸、奶奶、爷爷,这些请求就会沿着

* 这条链传送下去。

* 串起职责链有很多方法,这里用的是GOF书本里的方法,当然我们也可以使用链表等的方法来串起来。

* 下面我们来看看如何用代码来组织这个模式
\**********************************************************************************************************/

#include <stdio.h>
#include <iostream>
using namespace std;

// 这个模式需要定义一个公共接口,属于这条链里的对象全部都派生于它
class Handler
{
public:
    
    // 这个构造函数实际就是指定后继者
    Handler(Handler *s) : _successor(s) { }
    virtual ~Handler()
    {
    }

    // 处理请求的函数
    virtual void HandleRequest()
    {
        if(_successor)
        {
            cout << "孩子,我没有苹果,去问" << _successor->szName << "拿吧!" << endl;
            _successor->HandleRequest();
        }
        else
        {
            // 没有后继者了,必须想个办法来解决
            cout << "孩子,家里没有苹果了,只能出去买了。" << endl;
        }
    }

    // 是否有苹果
    virtual bool HasHandle()
    {
        return false;
    }
    virtual void SetHandler(Handler *s)
    {
        _successor = s;
    }

public:
    Handler *_successor;
    char szName[20];
};

// 好,接口已经有了,我们现在就可以去派生职责链里的每一个类
// 妈妈类
class Mom: public Handler
{
public:
    Mom(Handler *s) : Handler(s)
    {
        strcpy(szName, "妈妈");
    }
    virtual void HandleRequest()


    {
        if( HasHandle() )
        {
            // 给小孩苹果
            cout << "来,妈妈给你苹果" << endl;
        }
        else
        {
            // 把公共操作转到基类去,这是一个技巧
            // 当然你也可以使用_successor->HandleRequest();
            // 但是这样做如果你想在处理的前后加点额外的行为就很不方便了,要到每个派生类里去加
            Handler::HandleRequest();
        }
    }
    virtual bool HasHandle()
    {
        return false;
    }
};

// 相同的定义爸爸类
class Father: public Handler
{
public:
    Father(Handler *s) : Handler(s)
    {
        strcpy(szName, "爸爸");
    }
    virtual void HandleRequest()
    {
        if( HasHandle() )
        {
            // 给小孩苹果
            cout << "来,爸爸给你苹果" << endl;
        }
        else
        {
            Handler::HandleRequest();
        }
    }
    virtual bool HasHandle()
    {
        return false;
    }
};

// 奶奶类
class GrandMother: public Handler
{
public:
    GrandMother(Handler *s) : Handler(s)
    {
        strcpy(szName, "奶奶");
    }
    virtual void HandleRequest()
    {
        if( HasHandle() )
        {
            // 给小孩苹果
            cout << "来,奶奶给你苹果" << endl;
        }
        else
        {
            Handler::HandleRequest();
        }
    }
    virtual bool HasHandle()
    {
        return false;
    }
};

// 爷爷类
class GrandFather: public Handler


{
public:
    GrandFather(Handler *s) : Handler(s)
    {
        strcpy(szName, "爷爷");
    }
    virtual void HandleRequest()
    {
        if( HasHandle() )
        {
            // 给小孩苹果
            cout << "来,爷爷给你苹果" << endl;
        }
        else
        {
            Handler::HandleRequest();
        }
    }
    virtual bool HasHandle()
    {
        // 如果 return false 则程序需要处理没有后继者的情况
        // 这里是显示家里人都没苹果了,要出去买了
        return true; 
    }
};

// 要苹果
void WantApple(Handler *h)
{
    cout << "问" << h->szName << "拿苹果" << endl;
    h->HandleRequest();
}

void main()
{
    // 串起一条职责链
    GrandFather gf(NULL);
    Father f(&gf);
    GrandMother gm(&f);
    Mom m(&gm);

    WantApple(&m);
}


[解决办法]
首先,下面的代码是用于产生责任链的


    // 串起一条职责链
    GrandFather gf(NULL);
    Father f(&gf);
    GrandMother gm(&f);
    Mom m(&gm);

依次是妈妈-》奶奶-》爸爸-》爷爷。后者是前者的_successor,这个是通过调用基类的构造函数来完成的。

下面

WantApple(&m);

孩子开始要苹果,由于除了爷爷外,其他人都没有苹果。所以这个请求依次,在这个链上传到了爷爷那里,然后结束。传递的动作是通过调用基类的HandleRequest来完成的。

责任链还是比较直观的一个模式,你多搜搜,应该有很多不错的例子。

热点排行