【问题标题】:Where should be placed switch in strategy pattern without factory?没有工厂的策略模式中的switch应该放在哪里?
【发布时间】:2019-02-19 10:24:05
【问题描述】:

在任何策略模式示例中,主函数中都有创建每个可能的策略,例如:

Context cn = new Context(new CQuickSorter());
cn.Sort(myList);

cn = new Context(new CMergeSort());
cn.Sort(myList);

但是在某些地方我们必须选择我们应该使用什么策略,我们应该在哪里放置“开关”来选择正确的策略?在一个方法?我看到了带有“switch”方法的类,它返回了 OBJECT——正确的策略类实例,但那是工厂,而不是策略模式。

没有工厂的策略模式中应该在哪里“切换”?我有类似下面的方法 - 可以吗?

enum Operation
{
    Addition,
    Subtraction
}

public interface IMathOperation
{
    double PerformOperation(double A, double B);
}

class AddOperation : IMathOperation
{
    public double PerformOperation(double A, double B)
    {
        return A + B;
    }
}

class SubtractOperation : IMathOperation
{
    public double PerformOperation(double A, double B)
    {
        return A - B;
    }
}

class CalculateClientContext
{
    private IMathOperation _operation;

    public CalculateClientContext(IMathOperation operation)
    {
        _operation = operation;
    }

    public double Calculate(int value1, int value2)
    {
        return _operation.PerformOperation(value1, value2);
    }
}

class Service
{
    //In this method I have switch
    public double Calculate(Operation operation, int x, int y)
    {
        IMathOperation mathOperation = null;

        switch (operation)
        {
            case Operation.Addition:
                mathOperation = new AddOperation();
                break;
            case Operation.Subtraction:
                mathOperation = new SubtractOperation();
                break;
            default:
                throw new ArgumentException();
        }

        CalculateClientContext client = new CalculateClientContext(mathOperation);
        return client.Calculate(x, y);
    }
}

【问题讨论】:

  • 谁说工厂不能提供战略?
  • 所以没有目的只使用纯策略,因为带有策略的工厂要优雅得多。
  • 如果应该避免使用工厂,那么解决方案是 (1) 在策略上添加一个方法,指示该策略支持的操作 (2) 拥有一个包含所有策略的集合 (3) 其中需要使用策略迭代策略集合并找到支持该操作的策略并使用它
  • 这不是他们中哪一个更适合的问题,因为两者都有不同的用途。具体策略定义“如何做事”,工厂定义“使用哪种策略”。但是,您不需要工厂来创建策略。
  • 话虽如此,但没有通用的解决方案使用哪种模式以及如何使用。

标签: java c# design-patterns


【解决方案1】:

最灵活的方法是尽可能长时间地延迟决策(“切换”)。例如,如果您从以下内容开始:

Context cn = new Context(); // Don't care about the sorter yet...
cn.Sort(new CQuickSorter(), myList); // OK, NOW the sorter is needed, let's inject it now.

您可以在致电object.Sort() 之前随时做出决定。该决定可以在一个简单的 if-else 块中实现,也可以在一个复杂的工厂中实现。归根结底,最佳实施将取决于项目的复杂性。因此,没有硬性规则来定义开关的放置位置。

作为练习,您可以应用各种创建模式,看看它们是如何发挥作用的。这将帮助您了解何时使用每种设计模式。

【讨论】:

    【解决方案2】:

    当应用依赖注入时,域对象应该在composition root 中被实例化并连接在一起(即提供它们的依赖,例如策略)。用现代实用的术语来说,这意味着您的 DI 容器根据配置实例化并为上下文(客户端)对象提供策略。没有switch

    【讨论】:

      猜你喜欢
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-20
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      相关资源
      最近更新 更多