現在、私のコードには、文字列の値に応じて複数の if else ステートメントが分岐しています。すなわち
if(input == "condition1")
{
// Some logic
}
else if(input =="condition1")
{
// Some other logic
}
私は戦略パターンを使用する予定です。これは正しいアプローチですか?はいの場合、条件に応じて正しい具象戦略オブジェクトを作成するにはどうすればよいですか?
ありがとう
現在、私のコードには、文字列の値に応じて複数の if else ステートメントが分岐しています。すなわち
if(input == "condition1")
{
// Some logic
}
else if(input =="condition1")
{
// Some other logic
}
私は戦略パターンを使用する予定です。これは正しいアプローチですか?はいの場合、条件に応じて正しい具象戦略オブジェクトを作成するにはどうすればよいですか?
ありがとう
あなたが提供したコード例では、戦略はあなたがすでに持っているif条件からあなたを遠ざけるつもりはありません. 次のように、戦略オブジェクトを作成するために Factory が必要になります。
static class StrategyFactory
{
static IStrategy CreateStrategy(string input)
{
if (input == "condition1")
{
return new StrategyForCondition1();
}
else if (input == "condition2")
{
return new StrategyForCondition2();
}
}
}
これが、あなたの場合に戦略をお勧めしない理由です。
非常に洗練された代替ソリューションは、キーが入力文字列値であり、アクションが if ステートメントの内容である Dictionary を使用することです。
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/
コードサンプルの問題の1つは、文字列と比較していることです...これは可能な値である可能性があります。可能であれば、考えられるすべての条件を表す代わりに列挙型を作成します。これにより、予期しない文字列値に遭遇するのを防ぐことができます。
これは、C# のさまざまなパターン タイプの非常に優れた例が掲載されたすばらしいサイトです。
// 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()
なぜスイッチを使わないのですか?
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]();