职责链的应用

目的:使用职责链形式,替换复杂、特殊的if/else语句。
职责链定义:将处理逻辑封装起来,并按照从普通到特殊的层次优先级处理,如果在一个层次被正确处理,则处理结束;否则传递到下一层次。

一、常用示例

如果代码中,满足条件:condition2,只有在condition1失败后采取判断执行,condition n,只有在condition n-1失败时才执行(如下所示)。恭喜,这是一个职责链的雏形。

Funcition()
{
    if (condition 1)
    {
        statements 1;
    }
    else
    {
        if (condition 2)
        {
            statements 2;
        }
        else
        {
            ...;
        }
    }
    // no more statements;
}


 上述if代码段,实际集成了3个变化点(一般的分支语句,其实都有这3个变化点):
1.   实现条件逻辑的处理代码(封装到函数中)。
2.   将条件逻辑与处理代码关联。
3.   以条件逻辑选择分支,执行处理代码。
下面将以职责链形式,来重新实现代码的结构。

二、简单条件逻辑形式的职责链

原始代码中,变化点2、3混合在一起;而且代码格式没有显示的模块化。如果逻辑变得复杂,理解和维护都会逐渐变差。
简单改变程序代码,去掉else,减少缩进,得到简单条件逻辑形式的职责链。如下所示:

Funcition()
{
    if (condition 1)
    {
        statements 1;
        return;
    }

    

    if (condition 2)
    {
        statements 2;
        return;
    }
    

    ...;
 
}


这样做,不符合标准的“一个输入、一个输出”原则,但在这种情况下,多个输出的做法有以下优点:
1.  将变化点2以模块化代码段方式独立起来。
2.  使用代码段先后次序,来控制变化点3。

三、条件函数形式的职责链

简单条件逻辑的职责链中,变化点2仍然在调用函数中实现,对调用函数不妥。
将变化点2使用boo函数封装,得到条件函数形式的职责链。如下所示:

Funcition()
{
    if (DoCondition1Ok())
    {
        return;
    }

    if (DoCondition2Ok())
    {
        return;
    }
 
    ...;

}
 
bool DoCondition1Ok()
{
    if (condition 1)
    {
        statements 1;
        return true;
    }
    
    return false;
}
 
bool DoCondition2Ok()
{
    ...
} 

这样做,有以下优点:
1.  将变化点2封装到各层的处理函数中。

四、表驱动法的职责链

变化点3,仍然在调用函数中实现,对层次较少的处理,这种处理已经足够了。如果处理层次较多,则再使用表驱动法(参考“C++的表驱动法”)。步骤如下:
1.  将处理函数,按优先级,使用list结构存储起来;
2.  在调用函数中,使用迭代循环方式,逐个执行处理函数。
3.  如果处理函数执行正确,则返回;否则进入下一层继续执行,直到循环结束。

五、职责链模式

如果变化点1、2的结构比较复杂,则表驱动法中的函数级封装可能就显得力不从心。此时,使用职责链模式提供更大粒度的封装。将变化点1使用类封装,变化点3使用模式的“连接后继者”在创建时自动维护(参见四人帮的《设计模式》)。

参考文献

1. 《代码大全》(第2版)中文版,第18章 表驱动法。

2. 《设计模式》中文版,第5章,5.1 职责链。

 

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭