用表驱动法和Reflection实现代码重构

posted at 2021.9.5 15:20 by 风信子

表驱动法是一种设计思路,可以称为模式,也可以简单理解为查字典,例如有一个枚举类型Week

        enum Week

        {

            Monday,

            Tuesday,

            Wednesday,

            Thursday,

            Fridey,

            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.Fridey:

                    return "星期五";

                case Week.Saturday:

                    return "星期六";

                case Week.Sunday:

                    return "星期日";

                default:

                   throw new ArgumentOutOfRangeException("week", "星期值超出范围");

            }

        }

之所以说这种方法是丑陋的,原因在于两点:

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

2)不利于扩展。如果出现星期八、星期九怎么办?

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

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

Static void Mainstring[] args

{

    Console.WriteLineGetChineseweekInTableweek.Friday))

}

        static string GetChineseInTable(Week week)

        {

            string[] ChineseTable = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };

            return ChineseTable[(int)week];

        }

这是一种按照索引值驱动的表驱动法。枚举元素所代表的整型值,很容易和字符申数组索引组合起来了,用两行语句就可以完美地替代原先的GetChineseWeek方法。

但是,这种方法有局限性,完成的功能也很有效,如果将需求换成:星期一Mike打扫卫生、星期二Rose清理衣柜、星期三MikeRose没事可以吵吵架、星期四Rose要去Shopping......也就是说需求由静态属性变成了动态行为,那么事情就变得复杂了。

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

       static void Main(string[] args)

        {

            //Console.WriteLine(GetChineseWeek(Week.Monday));

            //Console.WriteLine(GetChineseInTable(Week.Thursday));

            SampleClass sample = new SampleClass();

            Var addMethod = typeof(SampleClass).GetMethod(ActionInTable(Week. Tuesday));

             addMethod.Invoke(sample, null);

        }

        static string ActionInTable(Week week)

        {

            string[] methods = { "Cleaning", "CleanCloset", "Quarrel", "Shopping", "Temp", "Temp", "Temp" };

            return methods[(int)week];

        }

        class SampleClass

        {

            public void Cleaning()

            {

                Console.WriteLine("打扫");

            }

            public void CleanCloset()

            {

                Console.WriteLine("清理衣柜");

            }

            public void Quarrel()

            {

                Console.WriteLine("吵架");

            }

            public void Shopping()

            {

                Console.WriteLine("购物");

            } 

        }

     控制台实际效果如下图所示:

Tags: , , ,

IT技术 | 防控BUG

添加评论

  Country flag

biuquote
  • 评论
  • 在线预览
Loading