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等設計模式。選擇的時候能夠考慮視具體狀況而定。
相關文章
相關標籤/搜索