Java 在没有工厂的情况下,应将开关置于策略模式的何处?

Java 在没有工厂的情况下,应将开关置于策略模式的何处?,java,c#,design-patterns,Java,C#,Design Patterns,在任何策略模式示例的主功能中,都会创建每个可能的策略,例如: Context cn = new Context(new CQuickSorter()); cn.Sort(myList); cn = new Context(new CMergeSort()); cn.Sort(myList); 但在某些地方,我们必须选择我们应该使用的策略,我们应该在哪里设置“开关”来选择正确的策略?用什么方法?我看到了一个带有“switch”方法的类,它返回了对象——正确的策略类实例,但这是工厂,而不是策略模

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

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

cn = new Context(new CMergeSort());
cn.Sort(myList);
但在某些地方,我们必须选择我们应该使用的策略,我们应该在哪里设置“开关”来选择正确的策略?用什么方法?我看到了一个带有“switch”方法的类,它返回了对象——正确的策略类实例,但这是工厂,而不是策略模式

没有工厂,战略模式的“转换”应该在哪里?我有下面这样的方法-可以吗

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);
    }
}

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

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块中实现,也可以在复杂的工厂中实现。归根结底,最好的实现取决于项目的复杂性。因此,没有硬性规定您应该将开关放置在何处


作为练习,您可以应用各种创建模式来查看它们的效果。这将帮助您了解何时使用每个设计模式。

在应用依赖项注入时,域对象应在内部实例化并连接在一起(即提供它们的依赖项,如策略)。在现代实用术语中,这意味着您的DI容器根据配置实例化并向上下文(客户机)对象提供策略。没有开关谁说工厂不能提供策略?因此,只使用纯策略是没有目的的,因为有策略的工厂要优雅得多。如果应该避免工厂,那么解决方案将是(1)在策略上添加一种方法,表明策略支持哪种操作(2)收集所有策略(3),其中需要使用策略迭代策略集合,找到支持操作和使用的策略。问题不在于哪种策略更适合,因为两者都有不同的用途。具体战略定义了“如何做事”,而工厂定义了“使用哪种战略”。然而,你不需要一个工厂来创建一个战略。尽管如此,没有通用的解决方案来使用哪种模式以及如何做到这一点。