【发布时间】:2010-09-30 19:25:00
【问题描述】:
我一直在阅读策略模式,并且有一个问题。我在下面实现了一个非常基本的控制台应用程序来解释我在问什么。
我已经读过,在实施策略模式时,使用“switch”语句是一个危险信号。但是,我似乎无法摆脱在这个例子中使用 switch 语句。我错过了什么吗?我能够从 Pencil 中删除逻辑,但我的 Main 现在有一个 switch 语句。我知道我可以轻松创建一个新的 TriangleDrawer 类,而不必打开 Pencil 类,这很好。但是,我需要打开 Main 以便它知道将哪种类型的 IDrawer 传递给 Pencil。如果我依赖用户输入,这只是需要做的吗?如果有办法在没有 switch 语句的情况下做到这一点,我很乐意看到它!
class Program
{
public class Pencil
{
private IDraw drawer;
public Pencil(IDraw iDrawer)
{
drawer = iDrawer;
}
public void Draw()
{
drawer.Draw();
}
}
public interface IDraw
{
void Draw();
}
public class CircleDrawer : IDraw
{
public void Draw()
{
Console.Write("()\n");
}
}
public class SquareDrawer : IDraw
{
public void Draw()
{
Console.WriteLine("[]\n");
}
}
static void Main(string[] args)
{
Console.WriteLine("What would you like to draw? 1:Circle or 2:Sqaure");
int input;
if (int.TryParse(Console.ReadLine(), out input))
{
Pencil pencil = null;
switch (input)
{
case 1:
pencil = new Pencil(new CircleDrawer());
break;
case 2:
pencil = new Pencil(new SquareDrawer());
break;
default:
return;
}
pencil.Draw();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
实施的解决方案如下所示(感谢所有回复的人!) 这个解决方案让我达到了使用新 IDraw 对象唯一需要做的事情就是创建它的地步。
public class Pencil
{
private IDraw drawer;
public Pencil(IDraw iDrawer)
{
drawer = iDrawer;
}
public void Draw()
{
drawer.Draw();
}
}
public interface IDraw
{
int ID { get; }
void Draw();
}
public class CircleDrawer : IDraw
{
public void Draw()
{
Console.Write("()\n");
}
public int ID
{
get { return 1; }
}
}
public class SquareDrawer : IDraw
{
public void Draw()
{
Console.WriteLine("[]\n");
}
public int ID
{
get { return 2; }
}
}
public static class DrawingBuilderFactor
{
private static List<IDraw> drawers = new List<IDraw>();
public static IDraw GetDrawer(int drawerId)
{
if (drawers.Count == 0)
{
drawers = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(type => typeof(IDraw).IsAssignableFrom(type) && type.IsClass)
.Select(type => Activator.CreateInstance(type))
.Cast<IDraw>()
.ToList();
}
return drawers.Where(drawer => drawer.ID == drawerId).FirstOrDefault();
}
}
static void Main(string[] args)
{
int input = 1;
while (input != 0)
{
Console.WriteLine("What would you like to draw? 1:Circle or 2:Sqaure");
if (int.TryParse(Console.ReadLine(), out input))
{
Pencil pencil = null;
IDraw drawer = DrawingBuilderFactor.GetDrawer(input);
pencil = new Pencil(drawer);
pencil.Draw();
}
}
}
【问题讨论】:
-
switch 语句会导致后面的开/关原则被违反是不好的。策略模式有助于将 switch 语句与您希望保持关闭的位置分开,但您仍然必须处理选择策略/实现的一些地方,它是 switch 语句、if/else/if 或使用 LINQ Where(即我最喜欢的 :-) 顺便说一句,策略模式还允许您轻松地模拟策略实现,从而帮助单元测试。
标签: c# design-patterns dependency-injection strategy-pattern coding-style