【问题标题】:In the strategy pattern can the strategy take the Context as parameter在策略模式中,策略能否以 Context 作为参数
【发布时间】:2010-01-09 17:49:21
【问题描述】:

反馈总结

我现在将关闭此广告(我认为不会有更多反馈)并尝试总结我的理解

  1. 使用“上下文”作为我的策略的参数会引入应该避免的紧密耦合,并且还可能迫使我公开可能应该隐藏在类中的属性。
  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();
  }
}

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

它会给出类似的东西

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

调用会给出

//The context
class Context
{
  ....

  public void Execute()
  {
    strategy.Execute(this);
  }
}

要避免这种“耦合”吗?还好吗?

【问题讨论】:

    标签: design-patterns strategy-pattern


    【解决方案1】:

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

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

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

    例如,如果 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);
    }
    

    在上面的代码中,Strategy 类在一个通用的 Integer 列表上进行操作,并且没有特别限制与 Context 类一起使用。 此外,还可以在定义 Strategy 类时使用泛型方法,以便 sort 方法不仅适用于整数,还适用于泛型类型。

    【讨论】:

    • 这就是为什么最好通过构造函数将上下文提供给实现类,这样我们就可以决定是否需要策略类的上下文。如果你把它放在方法中,那么它们是紧密耦合的。
    • 无论您是通过构造函数还是作为方法参数提供对 Context 的访问,都没有关系。这两种情况都会导致 Strategy 和 Context 类之间的紧密耦合。
    • 是的。你的权利。我的观点是,在某些情况下,策略类可能不需要上下文来工作。
    【解决方案2】:

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

    【讨论】:

    • 这意味着你对每个Context实例都有一个策略实例?如果有很多实例,这不是有点内存吗?
    • 它只是一个引用而不是整个对象,所以这里的内存不是问题。
    【解决方案3】:

    你的代码就是你的代码,写任何对你有意义的东西。不过,我确实有一点要注意。

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

    当策略将上下文作为参数时,解耦会减少。上下文的变化可能需要改变你的策略实施。就像之前的发帖人指出的那样,最好寻找一种方法使它们保持分离。

    话虽如此,只要您的意图是允许策略可互换并且您的代码实现了该意图,那么我认为没有问题。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2011-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多