Шаблон стратегии без операторов переключения?

Я читал кое-что о паттерне стратегии, и у меня есть вопрос. Я реализовал очень простое консольное приложение ниже, чтобы объяснить, о чем я спрашиваю.

Я читал, что наличие операторов 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();
        }
    }
}

Реализованное решение, показанное ниже (Спасибо всем, кто ответил!) Мне нужно было бы открыть 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();
        }
    }
}

Реализованное решение, показанное ниже (Спасибо всем, кто ответил!) Мне нужно было бы открыть 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();
            }
        }
    }
49
задан JSprang 1 October 2010 в 09:56
поделиться