没有“switch"语句的策略模式? [英] Strategy Pattern with no 'switch' statements?

查看:24
本文介绍了没有“switch"语句的策略模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读有关策略模式的一些资料,并有一个问题.我在下面实现了一个非常基本的控制台应用程序来解释我的要求.

I've been doing some reading on the Strategy Pattern, and have a question. I have implemented a very basic Console Application below to explain what I'm asking.

我已经读到在实施策略模式时使用switch"语句是一个危险信号.但是,我似乎无法摆脱在此示例中使用 switch 语句的情况.我错过了什么吗?我能够从 Pencil 中删除逻辑,但是我的 Main 现在有一个 switch 语句.我知道我可以轻松创建一个新的 TriangleDrawer 类,而不必打开 Pencil 类,这很好.但是,我需要打开 Main 以便它知道将哪种类型的 IDrawer 传递给 Pencil.如果我依赖用户输入,这就是需要做的事情吗?如果有没有 switch 语句的方法,我很乐意看到它!

I have read that having 'switch' statements is a red flag when implementing the strategy pattern. However, I can't seem to get away from having a switch statement in this example. Am I missing something? I was able to remove the logic from the Pencil, but my Main has a switch statement in it now. I understand that I could easily create a new TriangleDrawer class, and wouldn't have to open the Pencil class, which is good. However, I would need to open Main so that it would know which type of IDrawer to pass to the Pencil. Is this just what needs to be done if I'm relying on the user for input? If there's a way to do this without the switch statement, I'd love to see it!

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("()
");
        }
    }

    public class SquareDrawer : IDraw
    {
        public void Draw()
        {
            Console.WriteLine("[]
");
        }
    }

    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 对象唯一需要做的事情就是创建它.

Implemented Solution shown below (Thanks to all who responded!) This solution got me to the point where the only thing I need to do to use a new IDraw object is to create it.

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("()
");
        }

        public int ID
        {
            get { return 1; }
        }
    }

    public class SquareDrawer : IDraw
    {
        public void Draw()
        {
            Console.WriteLine("[]
");
        }

        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();
            }
        }
    }

推荐答案

策略并不是一个神奇的反切换解决方案.它所做的是模块化你的代码,而不是一个大的开关和业务逻辑在维护噩梦中混合在一起

Strategy isn't a magic anti-switch solution. What it does do is give modularise your code so that instead of a big switch and business logic all mixed up in a maintenance nightmare

  • 您的业务逻辑是隔离的,可以扩展
  • 您可以选择如何创建具体类(例如,请参阅工厂模式)
  • 您的基础架构代码(您的主要代码)可以非常干净,两者都没有

例如 - 如果您在 main 方法中使用 switch 并创建一个类,该类接受命令行参数并返回 IDraw 的实例(即它封装了该 switch),您的 main 又是干净的,并且您的 switch 在一个类中其唯一目的是实现该选择.

For example - if you took the switch in your main method and created a class which accepted the command line argument and returned an instance of IDraw (i.e. it encapsulates that switch) your main is clean again and your switch is in a class whose sole purpose is to implement that choice.

这篇关于没有“switch"语句的策略模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆