zoukankan      html  css  js  c++  java
  • 【转】编写高质量代码改善C#程序的157个建议——建议149:使用表驱动法避免过长的if和switch分支

    建议149:使用表驱动法避免过长的if和switch分支

    随着代码变得复杂,我们很容易被过长的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)不利于扩展。如果出现星期八、星期九怎么办?当然,星期制已经是固定的了,应该不会出现扩展情况。但是,换种情景来考虑,假设我们正在渲染动画怎么办?谁知道下一秒美工会提交我多少个动画呢?

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

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

            static string GetChineseWeek(Week week)
            {
                string[] chineseWeek = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };
                return chineseWeek[(int) week];
            }
    
            static void Main(string[] args)
            {
                Console.WriteLine(GetChineseWeek(Week.Friday));
            }

     这是一种按照索引值驱动的表驱动法。枚举元素代表的整型值,很容易和字符串数组索引结合起来,用两行语句就解决了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个建议》陆敏技

  • 相关阅读:
    ubuntu12.04 死机 卡屏 画面冻结解决方案
    Install Firefox 20 in Ubuntu 13.04, Ubuntu 12.10, Ubuntu 12.04, Linux Mint 14 and Linux Mint 13 by PPA
    ListView1.SelectedItems.Clear()
    android studio 下载地址
    jquery.slider.js jquery幻灯片测试
    jquery.hovermenu.js
    jquery.tab.js选项卡效果
    适配 placeholder,jquery版
    jquery.autoscroll.js jquery自动滚动效果
    将 Google Earth 地图集成到自己的窗体上的 简单控件
  • 原文地址:https://www.cnblogs.com/farmer-y/p/8022144.html
Copyright © 2011-2022 走看看