如何用策略替换(而不仅仅是移动)条件逻辑?

时间:2010-09-10 21:58:33

标签: design-patterns refactoring

Refactoring to Patterns中,作者通过让客户使用贷款工厂方法替换条件逻辑,其中每个方法都使用适当的策略用于给定的参数。但是,我觉得它已经将条件逻辑代码传递给客户端,它必须根据Loan工厂方法调用的参数进行选择。这不是移动而不是替换吗?

DP书籍也出现了同样的错觉:

例如,如果没有策略,将文本分成行的代码可能看起来像

void Composition::Repair () {
    switch (_breakingStrategy) {
    case SimpleStrategy:
        ComposeWithSimpleCompositor();
        break;
    case TeXStrategy:
        ComposeWithTeXCompositor();
        break;
    // ...
    }
    // merge results with existing composition, if necessary
}

策略模式通过将linebreaking任务委派给Strategy对象来消除此case语句:

void Composition::Repair () {
    _compositor->Compose();
    // merge results with existing composition, if necessary
}

是的,但是如何选择从哪个策略类实例化合成器?条件逻辑? 我看到如果上下文有一个hieararcy,那么条件逻辑会更远,因为每个子类都可以实例化相应的策略,但是这也适用于Composition :: repair(),其中每个子类将直接调用ComposeWithSimpleCompositor而不是的 ComposeWithTeXCompositor。

2 个答案:

答案 0 :(得分:4)

是的 - 选择设计模式有时会改变逻辑而不是替换它。

我真的不明白你的反对意见。一些决策逻辑已经在客户端,策略整合了决策。

在您的代码示例中

void Composition::Repair () {
    switch (_breakingStrategy) {
    case SimpleStrategy:
        ComposeWithSimpleCompositor();
        break;
    case TeXStrategy:
        ComposeWithTeXCompositor();
        break;
    // ...
    }
    // merge results with existing composition, if necessary
}

必须在某处提供_breakingStrategy字段,可能是客户端代码确定使用哪种组合方法,并将该决策的结果作为_breakingStrategy的值传递。

应用策略所做的唯一事情就是让决策提供一个策略子类而不是现在的“类型代码”,从而巩固决策。

当然,决定必须在某个地方做出决定。如果您认为Composition::Repair方法适合它,那么您当然可以根本不使用策略模式。

如果你想使用策略,但你不想要客户端中的逻辑(比现有的更多),包含类似开关的工厂方法可以提供它。

答案 1 :(得分:0)

条件逻辑被推向远离客户端的距离。这可能是可取的,因为在那个方向上可能已经做出选择(是的,通过条件逻辑)。这种方式考虑了条件逻辑。 选择的条件可能有不同的形式,包括文本。