C#: switch语句的重构

   switch语句是咱们平常工做中最多见也是争论最多的(goto被忽视的前提下)。在重构中也把switch语句当作是一种代码的坏味道。但如何改造现有的switch代码并在从此去避免呢?本文从两方面进行探讨。
1 类型转化
    在不一样的抽象层次上对于同一个对象可能会用不一样的定义。举个简单的例子,在计算器中,用户输入的操做符号多是字符型的,而程序内部实现的时候须要用枚举型。所以可能就会有这样的函数。
         public class Calculator
        {
                 public enum OPERATOR {Add, Minus, Multiply, Divide, Unknown};
                 public static OPERATOR GetOperator( char ch)
                {
                        OPERATOR op = OPERATOR.Unknown;
                         switch (ch)
                        {
                                 case '+':
                                        op = OPERATOR.Add;
                                         break;
                                 case '-':
                                        op = OPERATOR.Minus;
                                         break;
                                 case '*':
                                        op = OPERATOR.Multiply;
                                         break;
                                 case '/':
                                        op = OPERATOR.Divide;
                                         break;
                                 default:
                                         break;
                        }
                         return op;
                }
        }

   代码不长,不过写的过程当中我却拷贝几回(case部分的代码)。缘由就是代码的结构性重复仍是比较严重的,并且若是之后支持其余新的操做时候,这代码不只要改变,并且还会不断变冗长。认真想一想,避免的办法仍是有的,用Dictionary作一个映射表就能够实现。
 
     public class Calculator
        {
                 public enum OPERATOR { Add, Minus, Multiply, Divide, Unknown};
                 static private var OperatorMap = new Dictionary< char, OPERATOR> {
                        { '+', OPERATOR.Add },
                        { '-', OPERATOR.Minus },
                        { '*', OPERATOR.Divide },
                        { '/', OPERATOR.Multiply },
                };
                 public static OPERATOR GetOperator2( char ch)
                {
                         if (OperatorMap.ContainsKey(ch))
                                 return OperatorMap[ch];
                         else
                                 return OPERATOR.Unknown;
                }
        }
这样,不只代码简洁了不少,并且从本质上已经从逻辑代码维护变成了映射表的维护。
2 动做调用
接续刚才的例子,此次不只要实现操做符转化,并且要实现真正的运算。第一个反应又是想到了switch。实现以下:
 
     public class Calculator
        {
                 static public int Calculate( char op, int number1, int number2)
                {
                         int result = 0;
                         switch (GetOperator(op))
                        {
                                 case OPERATOR.Add:
                                        result = number1 + number2;
                                         break;
                                 case OPERATOR.Minus:
                                        result = number1 - number2;
                                         break;
                                 case OPERATOR.Multiply:
                                        result = number1 * number2;
                                         break;
                                 case OPERATOR.Divide:
                                        result = number1 / number2;
                                         break;
                                 default:
                                         throw new Exception( "Unsupported Operation!");
                        }
                         return result;
                }
        }
   跟以前遇到的问题有些相似,不过这回须要调用函数。经过.Net环境提供的Dictionary以及Func Delegate的解决以下:
         public class Calculator
        {
                 static private Dictionary<OPERATOR, Func< int, int, int>> calculationAction = new Dictionary<OPERATOR, Func< int, int, int>> {
                        { OPERATOR.Add, Add },
                        { OPERATOR.Minus, Minus },
                        { OPERATOR.Multiply, Multiply },
                        { OPERATOR.Divide, Divide }            
                };
                 public static OPERATOR GetOperator2( char ch)
                {
                         if (OperatorMap.ContainsKey(ch))
                                 return OperatorMap[ch];
                         else
                                 return OPERATOR.Unknown;
                }
                 static int Add( int number1, int number2)
                {
                         return number1 + number2;
                }
                 // Others are omitted here for brevity
        }

经过这个简单的例子,咱们能够看出Switch一般会带来一些结构性的重复,经过利用Dictionary等二维表结构,咱们能够尽可能去避免switch语句,从而实现更好的灵活性和可维护性。最后须要支持的是,在Switch语句的重构过程当中须要注意几点:
* 共通化以使得各个case中调用函数的签名一致 * if...else if...else结构同switch在某些状况下具备互换性,也能够考虑这种方法 * switch语句的重构是也能够考虑State Pattern以及Strategy Pattern等设计模式。选择的时候能够考虑视具体状况而定。
相关文章
相关标签/搜索