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

时间:2010-01-09 17:49:22

标签: design-patterns strategy-pattern


反馈摘要

我现在关闭这个thead(我想不会有更多的反馈)并尝试总结我的理解

  1. 使用“Context”作为我的策略的参数引入了应该避免的紧密耦合,也可能迫使我暴露应该保留在类中的属性。
  2. 为了最大程度地减少耦合,最好提供所需的值,或者至少使用接口而不是具体类型来制定策略。

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

    让我们采取以下经典实现

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

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

    它会提供类似

    的内容
    //The strategy
    interface IStrategy  
    {  
      void Execute(Context arg);  
    }  
    

    并且调用将给出

    //The context
    class Context
    {
      ....
    
      public void Execute()
      {
        strategy.Execute(this);
      }
    }
    

    是否要避免这种“耦合”?可以吗?

4 个答案:

答案 0 :(得分: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);
}

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

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

答案 1 :(得分:5)

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

答案 2 :(得分:2)

您的代码是您的代码,写下对您有意义的代码。但是,我确实有一点需要注意。

策略模式的目的是创建一系列可互换的策略。像许多设计模式一样,它从分离中获益。在这种情况下,我们将行为与使用此类行为的类解耦。

当策略将上下文作为参数时,减少了解耦。上下文中的更改可能需要更改策略实现。就像前面提到的海报一样,最好找一种让它们分离的方法。

话虽如此,只要您的意图是允许策略可以互换并且您的代码完成了这个意图,那么我就不会发现问题。

答案 3 :(得分:0)

根据这本书,有几种方法,包括您的方法:

enter image description here