在策略模式中,策略可以将Context作为参数

Fre*_*ata 10 design-patterns strategy-pattern


反馈摘要

我现在将关闭这个(我想没有更多的反馈),并试着总结一下我的理解

  1. 使用"Context"作为我的策略的参数引入了应该避免的紧密耦合,并且还可能迫使我暴露应该保留在类中的属性.
  2. 为了最小化耦合,最好提供所需的值或至少使用接口而不是具体类型的策略.

我正在努力清楚地了解战略模式,并且我问自己,策略取决于上下文是好还是坏.

让我们采取以下经典实现

//The strategy
interface IStrategy  
{  
  void Execute();  
}  

class ConcreteStrategyA : IStrategy
{
  public void Execute()
  {
    Console.WriteLine( "Called ConcreteStrategyA.Execute()" );
  }
}

class ConcreteStrategyB : IStrategy
{
  public void Execute()
  {
    Console.WriteLine( "Called ConcreteStrategyB.Execute()" );
  }
}

//The context
class Context
{
  IStrategy strategy;

  // Constructor
  public Context(IStrategy strategy)
  {
    this.strategy = strategy;
  }

  public void UpdateContext(IStrategy strategy)
  {
    this.strategy = strategy;
  }

  public void Execute()
  {
    strategy.Execute();
  }
}
Run Code Online (Sandbox Code Playgroud)

我见过的所有例子都有非常简单的策略,它们采用基本参数(例如整数).我想知道的是,如果策略使用Context来完成工作,那么是否存在问题.

它会给出类似的东西

//The strategy
interface IStrategy  
{  
  void Execute(Context arg);  
}  
Run Code Online (Sandbox Code Playgroud)

并且调用会给

//The context
class Context
{
  ....

  public void Execute()
  {
    strategy.Execute(this);
  }
}
Run Code Online (Sandbox Code Playgroud)

是否要避免这种"耦合"?好吗?

sat*_*esh 7

我在您的方法中看到的一个问题是,具体的Context类与Strategy类的实例之间存在紧密耦合.这意味着Strategy类只能与Context类一起使用.避免这种情况的一种方法是使您的策略类依赖(或使用)"Context"类将实现的接口.

编辑 此外,当Strategy类具有Context类的实例时,这些类必须从Context类获取显式数据.这意味着在Context类中为策略类添加getter(必要时)以获取所需的数据.但添加吸气剂并不一定是一个好的OO实践,因为更多的吸气剂会带来破坏封装的风险.

您可以想到的另一种方法是将Context类的引用(this)传递给策略类中的方法,而是将所需的数据传递给Strategy类.

例如,如果Context类是这样的:(代码是Java)

Context {
   IStrategy strategy;
   List<Integer> scores;

   public Context(IStrategy strategy)
   {
        this.strategy = strategy;
        scores = new ArrayList<Integer>
   }

   public print() {
       strategy.sort(scores);
   }
}

public interface IStrategy<Integer> {
    public void sort(List<Integer> l);
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,Strategy类在通用的Integer列表上运行,并不特别限制与Context类一起使用.另外,在定义Strategy类时可以使用泛型方法,这样sort方法不仅适用于Integers,还适用于泛型类型.


Ben*_*nny 5

恕我直言,没关系.但我更喜欢通过策略实现类的构造函数将上下文传递给策略.