对策略设计模式感到困惑

Confused about strategy design pattern

我不明白为什么要在策略设计模式中使用上下文模块(我们将在下面的代码中看到),它的作用是什么?让我们看看策略设计模式的一部分。

public interface Strategy {
    public int doOperation(int num1, int num2);
}

public class OperationAdd implements Strategy {
    @Override 
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

public class OperationSubstract implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}

从上面的代码来看,我们可以这样调用不同的算法:

Context context = new Context(new OperationAdd());
context.executeStrategy(10,5);

我完全不明白,为什么不能直接调用子class而是使用Context层。在我看来,就像这样:

Strategy addStrategy = new OperationAdd();
addStrategy.doOperation(10, 5);

它只是展示了您可以通过使用组合和策略模式来更改 class 的功能。不是最好的例子。

上下文将 return 5 或 15 给定相同的输入并执行相同的方法,而不更改上下文对象中的代码。您只需指定要使用的策略。

尽管我不喜欢这个例子,但我还是会解释一下使用 Context 的好处。

这里已经用Context包裹了所有的策略。如果你正确地使用它,它可以充当一个迷你 Facade 或 Factory。

如果我必须实施Context,我将在构建期间创建一次所有策略并实施Factory_Method to return which Strategy to be used based on Input parameter. Even we can avoid if else condition with this approach

获得策略后,我将简单地调用 executeStrategy,它隐藏了我的策略的内部结构。

在没有Context的情况下,调用者必须在执行策略之前获取具体的策略。如果您在应用程序中调用 AddSubtract 策略 100 次,则必须公开特定的具体策略。

如果我有 Context,它会通过隐藏我的策略来提供正确的策略,并且它可以在运行时切换策略。

换句话说:来自维基百科的Strategy_Pattern提供了很好的例子。这个例子可能与问题无关,但它将提供很好的洞察力来理解策略模式的有效性(特别是部分:策略和open/closed原则 )

为了更好地理解 Strategy 模式,请查看此 post:

Real World Example of the Strategy Pattern

上下文在运行时决定必须执行哪个策略。如果您自己创建一个具体的策略实例并调用它,那么它就变成了 编译时间 的东西,而不是策略模式的目标。

此外,策略模式的上下文在 post dependency-injection 时代已经变得次要了。

在依赖注入出现之前,运行时需要一个 class,它会根据客户需求执行 if-else 和 select 适当的具体策略实施。此 class 被称为上下文。

当依赖注入出现时,可以在运行时插入场景特定的具体策略实例。所以,做这个依赖注入的容器开始扮演上下文的角色。

使用任何设计模式的目的都是最大化内聚和松散耦合。 在策略设计模式中,客户端与上下文交互并设置算法名称或策略名称。所以它在客户端和实现之间保持松耦合。

因此我们可以为一个接口实现任意数量的实现,而客户端不需要意识到这一点,因为客户端只提供算法并获得对所需实现方法的访问权。因此,为了提供松散耦合并保持高度抽象,最好使用上下文,以便可以在运行时使用运行时多态性来决定实现