当前位置: 首页 > 知识库问答 >
问题:

开关语句的替代方法

叶德运
2023-03-14
    null

代码如下所示:

    public class SomeType
    {
        // Some properties.
    }

    public enum SomeTrigger
    {
        Loaded,
        Initial,
        Timer,
        Final
    }


    public class SomeBaseObject
    {
        // 
        // I am not allowed to change this class. It is not mine.
        //

        protected Dictionary<string, SomeType> Input;
        protected Dictionary<string, SomeType> Output;


        // Timer is evaluated every 2 sec.
        public virtual void Execute(SomeTrigger trigger, string value)
        {
            switch (trigger)
            {
                case SomeTrigger.Loaded:
                    break;
                case SomeTrigger.Initial:
                    break;
                case SomeTrigger.Timer:
                    break;
                case SomeTrigger.Final:
                    break;
                default:
                    break;
            }
        }

        // The rest of code...
    }

和我想提高的班级:

public class SomeSpecificObject : SomeBaseObject
    {
        private bool isInitializationCompleted;
        private string connection;

        public override void Execute(SomeTrigger trigger, string value)
        {
            switch (trigger)
            {
                case SomeTrigger.Loaded:
                    this.OnLoaded();
                    break;
                case SomeTrigger.Initial:
                    this.OnInitial();
                    break;
                case SomeTrigger.Timer:
                    this.OnTimer();
                    break;
                case SomeTrigger.Final:
                    this.OnFinal(value);
                    break;
                default:
                    break;
            }
        }

        private void OnLoaded()
        {
            // Read Input and Output collection.
        }

        private void OnInitial()
        {
            // Initialization (connect to the server).
            // Bla bla bla
            this.connection = //Value from the plug-in;
            this.isInitializationCompleted = true;

        }

        private void OnTimer()
        {
            if (isInitializationCompleted)
            {
                // Do something
                // Connection is using here.
                // Calculate values on a Input collection, etc.
            }
        }

        private void OnFinal(string value)
        {
            if (isInitializationCompleted)
            {
                // something with "value"
                // Connection is using here.
                // Clear state.
            }
            else
            {
                // Connection is using here.
                // Cancel inistialization
            }
        }
    }

我该怎么办?每个字段都在使用,但每个触发器都在使用。另外,这种情况有点特殊(OnFinalMethod需要参数)。基于上面的文章,我尝试重构这段代码,但没有成功。

My attempts to apply some tips: 

    public interface ITrigger
    {
        void Execute();
    }

    public class LoadedTrigger : ITrigger
    {
        public void Execute()
        {
            throw new NotImplementedException();
        }
    }

    //
    // Exactly the same class for the rest cases.
    //
    public class TriggerHandler
    {
        private Dictionary<SomeTrigger, ITrigger> triggerDictionary;

        public TriggerHandler()
        {

            triggerDictionary.Add(SomeTrigger.Loaded, new InitialTrigger());
    // and for the rest

        }

        public void HandleTrigger(SomeTrigger trigger)
        {
            triggerDictionary[trigger].Execute();
        }
    }

你知道吗?:)

共有1个答案

姚淳
2023-03-14

一开始,switch语句总体上没有什么问题。仅仅在代码中使用它就会产生一些隐含的结构限制。如果这些限制中的一个与代码的发展方式相矛盾,换句话说,如果需求以开关逻辑变得过时的方式发生变化,那么继续在代码中保留它将导致技术债务。

从上面的代码中,并不清楚对它的要求是什么。例如,为什么首先需要有Execute方法?可以直接用just loadd()、Initial()和其他方法替换它吗?这显然会消除开关。

另一种方法是使用事件对象而不是枚举,并使用方法重载:Execute(LoadedTrigger...),...,Execute(FinalTrigger...,...)。

如果您想在运行时添加处理程序,使用dictionary的方法是很好的(是吗?),但缺少的部分是检查触发器类型和调用不同的execute方法:

var t = triggerDictionary[trigger];
if (t is SimpleTrigger st) st.Execute();
else if (t is AdvancedTrigger at) at.Execute(value);

或者,向触发器的execute方法添加值。但如果没有这样的要求,又何必费心呢?

例如。TimerTrigger对象需要知道初始化是成功的。

您可能需要一个状态机。开关是为简单状态机编写转换代码的一种常用方法。

 类似资料:
  • 问题内容: 因此,我今天编写了一种方法,该方法结合了嵌套开关语句的使用,并且代码对我来说看起来很简洁明了,但是有人告诉我,嵌套开关语句通常不是最好的处理方法,因为它们可能会使更多的语句变得混乱。切换添加的语句。这是我的代码的示例: 因此,我的问题是,从本质上讲,什么是这些switch语句的合适替代方案? 问题答案: 我建议您用对过程的调用替换每个嵌套的switch语句,然后该过程将执行嵌套的swi

  • 我想用Python编写一个函数,根据输入索引的值返回不同的固定值。 在其他语言中,我会使用或语句,但Python似乎没有语句。在这个场景中,推荐的Python解决方案是什么?

  • 问题内容: Java中goto关键字的替代功能是什么? 由于Java没有goto。 问题答案: 你可以使用带标签的BREAK语句: 但是,在正确设计的代码中,你不需要GOTO功能。

  • 我们的老师让我们创建一个关于给定情况的java程序,即使用if/else的每小时工资率,这就是我得出的结果,我对此感到高兴(我只是一个初学者)。接下来的指令是用switch语句替换if/else。他还没有讨论switch语句。我试图搜索它们,但我无法理解。请帮忙。非常感谢。 这就是确切的指示:1。使用if/else构造编写一个程序,该程序将根据工作小时数计算人员工资。注意ff:工资率为每小时35菲

  • 问题内容: 我有一个字符串数组,每个字符串包含3个字母。每3个字母(每个元素)对应一个唯一字母。我需要从字符串数组创建一个char数组。 我能想到的唯一方法是遍历字符串数组中的每个元素,并使用一个长的switch语句来确定其关联的单个字符。 还有什么其他方法可以实现? 问题答案: 如果是映射/查找,那么通常地图/词典可以解决您的问题。C#中的此类结构示例: 如果有这样的映射,则只需从映射中查找字母

  • 问题内容: ️ 2020年6月23日编辑:从Xcode 12开始,ViewBuilder将同时支持switch和let语句! 我一直在尝试使用SwiftUI复制我的应用程序。它有一个RootViewController,根据枚举值,它显示了一个不同的子视图控制器。与在SwiftUI中一样,我们使用视图而不是视图控制器,我的代码如下所示: 不幸的是,我收到警告: 包含控制流语句的闭包不能与funct