2

到目前为止,我的代码有多个 if else 语句分支,具体取决于字符串的值。IE

if(input == "condition1")
{
    // Some logic
}
else if(input =="condition1")
{
    // Some other logic
}

我打算使用策略模式。这是正确的方法吗?如果是,如何根据条件创建正确的具体策略对象?

谢谢

4

3 回答 3

3

在您提供的代码示例中,策略不会让您摆脱已有的 if 条件。您最终需要一个工厂来创建您的策略对象,如下所示:

static class StrategyFactory
{
    static IStrategy CreateStrategy(string input)
    {
        if (input == "condition1")
        {
            return new StrategyForCondition1();
        }
        else if (input == "condition2")
        {
            return new StrategyForCondition2();
        }
    }
}

这就是为什么我不会为您的案例推荐 Strategy 的原因。

一个非常优雅的替代解决方案是使用字典,其中键是输入字符串值,动作是 if 语句的内容:

var actions = new Dictionary<string, Action>
{
    {"condition1", () => Console.WriteLine("condition1")},
    {"condition2", NameOfMethodThatHandlesCondition2}
};

现在,此解决方案的美妙之处在于您只需使用 1 行代码即可使用它:

actions[input];

请参阅此处的示例:http: //elegantcode.com/2009/01/10/refactoring-a-switch-statement/

您的代码示例中的一个问题是您正在与一个字符串进行比较......这可能是任何可能的值。如果可能,请创建一个表示所有可能条件的枚举。这将防止遇到您没有预料到的字符串值。

于 2012-08-17T15:22:57.783 回答
0

这是一个很棒的站点,其中包含 C# 中不同模式类型的一些非常好的示例。

C# 和 VB 中的策略设计模式

// Strategy pattern -- Structural example
using System;

namespace DoFactory.GangOfFour.Strategy.Structural
{
  /// <summary>
  /// MainApp startup class for Structural
  /// Strategy Design Pattern.
  /// </summary>
  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
      Context context;

      // Three contexts following different strategies
      context = new Context(new ConcreteStrategyA());
      context.ContextInterface();

      context = new Context(new ConcreteStrategyB());
      context.ContextInterface();

      context = new Context(new ConcreteStrategyC());
      context.ContextInterface();

      // Wait for user
      Console.ReadKey();
    }
  }

  /// <summary>
  /// The 'Strategy' abstract class
  /// </summary>
  abstract class Strategy
  {
    public abstract void AlgorithmInterface();
  }


  /// <summary>  
  /// A 'ConcreteStrategy' class
  /// </summary>
  class ConcreteStrategyA : Strategy
  {
    public override void AlgorithmInterface()
    {
      Console.WriteLine("Called ConcreteStrategyA.AlgorithmInterface()");
    }
  }

  /// <summary>  
  /// A 'ConcreteStrategy' class
  /// </summary>
  class ConcreteStrategyB : Strategy
  {
    public override void AlgorithmInterface()
    {
      Console.WriteLine("Called ConcreteStrategyB.AlgorithmInterface()");
    }
  }

  /// <summary>
  /// A 'ConcreteStrategy' class
  /// </summary>
  class ConcreteStrategyC : Strategy
  {
    public override void AlgorithmInterface()
    {
      Console.WriteLine("Called ConcreteStrategyC.AlgorithmInterface()");
    }
  }

  /// <summary>
  /// The 'Context' class
  /// </summary>
  class Context
  {
    private Strategy _strategy;

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

    public void ContextInterface()
    {
      _strategy.AlgorithmInterface();
    }
  }
}

Output
Called ConcreteStrategyA.AlgorithmInterface()
Called ConcreteStrategyB.AlgorithmInterface()
Called ConcreteStrategyC.AlgorithmInterface()
于 2012-08-17T15:20:57.930 回答
-2

为什么不直接使用开关?

switch (input) {
  case "condition1": 
    // do stuff
    break;
  case "condition2":
    // do stuff....
    break;
  default:
    // default stuff
    break;
}

或未能使用Dictionary<string,Action>

var actions=new Dictionary<string,Action> { { "condition1", () => {code}}, {"condition2",) => {code}};

然后..

if (actions.ContainsKey(input)) actions[input]();
于 2012-08-17T15:20:40.090 回答