Ho letto un po 'sul modello di strategia e ho una domanda. Ho implementato un'applicazione di console molto di base qui sotto per spiegare cosa sto chiedendo.Schema della strategia senza istruzioni 'switch'?
Ho letto che avere istruzioni 'switch' è una bandiera rossa quando si implementa il modello di strategia. Tuttavia, non riesco a staccarmi dall'avere un'istruzione switch in questo esempio. Mi sto perdendo qualcosa? Sono stato in grado di rimuovere la logica dalla matita , ma il mio principale ha ora un'istruzione switch in esso. Capisco che potrei facilmente creare una nuova classe TriangleDrawer e non aprire la classe Pencil, che è buona. Tuttavia, avrei bisogno di aprire Main in modo da sapere quale tipo di ID2IDrawer passare alla matita . Questo è solo ciò che deve essere fatto se mi affido all'utente per l'input? Se c'è un modo per farlo senza l'istruzione switch, mi piacerebbe vederlo!
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();
}
}
}
soluzione implementata mostrato di seguito (Grazie a tutti coloro che hanno risposto!) Questa soluzione mi ha fatto al punto in cui l'unica cosa che devo fare per utilizzare un nuovo idraw oggetto è quello di crearlo.
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();
}
}
}
L'istruzione di commutazione che può causare la violazione del principio di apertura/chiusura in seguito è errata. Il modello di strategia aiuta a separare l'affermazione dello switch dal luogo in cui si desidera mantenerlo chiuso, ma devi ancora scegliere la strategia/implementazione in cui sia l'istruzione switch, if/else/if o l'uso di LINQ Where (che è il mio preferito :-) A proposito, il modello strategico aiuta anche il collaudo delle unità permettendoti di simulare facilmente l'implementazione della strategia. – kimsk