策略设计模式是否适合基于字符串比较的逻辑?

时间:2012-08-17 15:17:41

标签: c# design-patterns strategy-pattern

截至目前,我的代码有多个if else语句分支,具体取决于字符串的值。即。

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

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

由于

3 个答案:

答案 0 :(得分:3)

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

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

这就是为什么我不会为你的案例推荐策略。

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

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

现在,这个解决方案的优点在于您只使用一行代码:

actions[input];

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

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

答案 1 :(得分:0)

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

Strategy Design Patterns in C# and 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()

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