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

Posted

技术标签:

【中文标题】如何用策略替换(而不仅仅是移动)条件逻辑?【英文标题】:How to Replace (and not just move) Conditional Logic with Strategy? 【发布时间】:2010-09-10 21:58:32 【问题描述】:

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

DP 书重蹈覆辙:

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

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

策略模式通过将换行任务委托给策略对象来消除这种情况声明:

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

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

【问题讨论】:

【参考方案1】:

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

不过,我真的不明白你的反对意见。一些决策逻辑已经在客户端中,并且策略巩固了决策。

在您的代码示例中

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

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

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

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

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

【讨论】:

【参考方案2】:

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

【讨论】:

以上是关于如何用策略替换(而不仅仅是移动)条件逻辑?的主要内容,如果未能解决你的问题,请参考以下文章

Netezza SQL - 如何用条件替换两个逗号之间的字符串

按钮条件逻辑配置化的可选技术方案

如何用dict \ df在一列上用条件替换列列表

优雅的替换if-else语句

优雅的替换if-else语句

白盒测试技术-逻辑覆盖