zoukankan      html  css  js  c++  java
  • C#使用表驱动算法实现多层if或者switch语句重构

    加入我们有一个类枚举类型Week如下:

    enum Week
        {
            Monday,
            Tuesday,
            Wednesday,
            Thursday,
            Friday,
            Saturday,
            Sunday
        }

     如果要把Week的元素值用中文输出,简单而丑陋的方法也许是封装一个GetChineseWeek方法:

    static string GetChineseWeek(Week week)
            {
                switch (week)
                {
                    case Week.Monday:
                        return "星期一";
                    case Week.Tuesday:
                        return "星期二";
                    case Week.Wednesday:
                        return "星期三";
                    case Week.Thursday:
                        return "星期四";
                    case Week.Friday:
                        return "星期五";
                    case Week.Saturday:
                        return "星期六";
                    case Week.Sunday:
                        return "星期日";
                    default:
                        throw new ArgumentOutOfRangeException("week","星期值超出范围");
                }
            }

     之所以说这种方法太丑陋,是因为:

    1)分支太长了,而且出现了重复代码。

    2)不利于扩展。如果出现星期八、星期九怎么办?当然,星期制已经是固定的了,应该不会出现扩展情况。但是,换种情景来考虑,假设我们正在渲染动画怎么办?谁知道下一秒美工会提交我多少个动画呢?

    一种解决方案是使用多态,它很好的符合了“开闭”原则。如果增加条件分支,不必修改源代码,直接增加子类就可以了。利用多态避免分支,这里暂且不表,本建议要采用的是“表驱动法”。

    可以把表驱动简单理解为查字典。代码如下表示:

     1 static string GetChineseWeek(Week week)
     2         {
     3             string[] chineseWeek = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };
     4             return chineseWeek[(int) week];
     5         }
     6 
     7         static void Main(string[] args)
     8         {
     9             Console.WriteLine(GetChineseWeek(Week.Friday));
    10         }

     这是一种按照索引值驱动的表驱动法。枚举元素代表的整型值,很容易和字符串数组索引结合起来,用两行语句就解决了GetChineseWeek方法。但是,这种方法有局限性,如果需要换成:星期一Mike打扫卫生、星期二Rose清理衣柜、星期三Mike和Rose没事可以吵吵架、星期四Rose要去Shopping,也就是说需求由静态属性变成了动态行为,那么事情就变得复杂了。

    遇上这种情况,我们可能会想到使用多态,在这里依然使用表驱动法加上一点反射来实现这类动态的行为,代码如下:

    class Program
        {
            static string ActionInTable(Week week)
            {
                string[] methods = { "Cleaning", "CleanCloset", "Quarrel", "Shopping", "Temp", "Temp", "Temp" };
                return methods[(int)week];
            }
    
            static void Main(string[] args)
            {
                SampleClass sample=new SampleClass();
                var addMethod = typeof (SampleClass).GetMethod(ActionInTable(Week.Monday));
                addMethod.Invoke(sample, null);
            }
        }
    
        class SampleClass
        {
            public void Cleaning()
            {
                Console.WriteLine("打扫");
            }
            public void CleanCloset()
            {
                Console.WriteLine("整理衣橱");
            }
            public void Quarrel()
            {
                Console.WriteLine("吵架");
            }
            public void Shopping()
            {
                Console.WriteLine("购物");
            }
            public void Temp()
            {
                Console.WriteLine("临时安排");
            }
        }

    转自:《编写高质量代码改善C#程序的157个建议》陆敏技

  • 相关阅读:
    聊聊Unity2018的LWRP和混合光照
    不能直接获取?聊聊如何在Shader Graph中获取深度图
    还原堆栈信息,分析地形系统使用ASTC格式的纹理导致Crash的问题
    巧妙设置Texture Type,将ShadowMask内存占用变成之前的1/4
    开发自定义ScriptableRenderPipeline,将DrawCall降低180倍
    Signed Distance Field Shadow in Unity
    Daily Pathtracer!安利下不错的Pathtracer学习资料
    聊聊LightProbe原理实现以及对LightProbe数据的修改
    Scala学习笔记(六):本地函数、头等函数、占位符和部分应用函数
    Scala学习笔记(五):内建控制循环
  • 原文地址:https://www.cnblogs.com/tianyang1027/p/10345055.html
Copyright © 2011-2022 走看看