Я читал о шаблоне стратегии и задал вопрос. Я объяснил, что я прошу, для этого я использовал базовое консольное приложение.Шаблон стратегии без инструкций 'switch'?
Я читал, что при выполнении стратегического шаблона наличие операторов «switch» является красным. Тем не менее, я не могу уклониться от предложения switch в этом примере. Я что-то упускаю? Я смог удалить логику с Карандаш, но у моего Main есть инструкция switch в нем сейчас. Я понимаю, что я мог бы легко создать новый класс TriangleDrawer, и не нужно было бы открывать класс Pencil, что хорошо. Однако мне нужно было бы открыть Main, чтобы он знал, какой тип IDrawer перейдет на Карандаш. Это то, что нужно сделать, если я полагаюсь на пользователя для ввода? Если есть способ сделать это без оператора 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, либо/else/if, либо с помощью LINQ Where (который мой любимый :-) Кстати, стратегический паттерн также помогает модульное тестирование, позволяя вам также легко имитировать реализацию стратегии. – kimsk