在這篇文章中,我要來嘗試透過重構的方法,將原來使用 C# Switch 寫的程式碼,重構成為比較清爽與好閱讀和好維護的程式碼,首先,我們來看看原先使用 Switch 所寫的程式碼。
在這裡,我會建立 RefactorSwitchDictionary 專案來進行說明 (這裡的練習專案,將會建立一個 .NET Core 主控制台應用程式專案)
在這個範例中,我們要設計一個支援類別,在這個支援類別中僅有一個方法,這個方法將會接受一個字串的傳入,接著,根據字串的內容與意義,產生相對應的顏色 Color 類別物件。其實,任何會寫 C# 程式碼的人,應該對於這樣的需求並不陌生,我們可以寫很多 if ... else if ... else if ... else ... 的連貫敘述程式碼,或者,使用 Switch 關鍵字,搭配許多的 case 關鍵字來寫出這樣的方法,如下列程式碼。
在底下的程式碼看似十分完美,但是,若您可以支援的顏色名稱,超過了 30 個以上,那麼,這個方法將會變成十分的長,而且,說實在的,要維護起來,首先要看過這些程式碼,依序看完這些程式碼後,接著要進行增加新的顏色名稱或者修改錯誤,也不是這麼的方便。(我們在這裡,對於每個 case 關鍵字後要執行的工作,設定為僅有一行敘述,而且每個 case 關鍵字之後要執行的功能,都十分類似;但是,若在這個 switch ... case ... case .. 這樣的程式碼中,每個 case 要處理的動作皆完全不相同,對於這樣的情況,我們可以使用其他的重構技巧來進行解決,我們並不在這裡進行討論)。
public class StringToColor
{
public Color Transfer(string name)
{
Color transferResult;
switch (name.ToLower())
{
case "red":
transferResult = Color.FromArgb(0xFF, 0xFF, 0x00, 0x00);
break;
case "green":
transferResult = Color.FromArgb(0xFF, 0x80, 0x80, 0x80);
break;
case "blue":
transferResult = Color.FromArgb(0xFF, 0x00, 0x00, 0xFF);
break;
default:
throw new ArgumentException("不正確的顏色名稱");
}
return transferResult;
}
}
在這裡,我們來看看如何使用這個支援類別的將字串轉換成為 Color 類別物件。
首先,我們建立一個 StringToColor 類別的物件,緊接著呼叫 Transfer 方法,我們在這個方法傳入一個字串 (Red) 進去,當然,我們將會取得一個 Color 物件,並且把這個物件的顏色屬性顯示在螢幕上。
class Program
{
static void Main(string[] args)
{
string MyColorName = "Blue";
Console.WriteLine("使用 Swith 來設計方法");
StringToColor foo = new StringToColor();
Color fooColor = foo.Transfer(MyColorName);
Console.WriteLine($"{MyColorName} = A:{fooColor.A} R:{fooColor.R} G:{fooColor.G} B:{fooColor.B}");
Console.WriteLine("Press any key for continuing...");
}
}
這裡是執行結果
使用 Swith 來設計方法
Blue = A:255 R:0 G:0 B:255
Press any key for continuing...
剛剛的轉換字串到顏色物件的方法程式碼,似乎還滿簡單的,但試想,若隨著需求增加,顏色文字不斷的增加,您將會看到長長的 Switch ... case 敘述。現在,讓我們使用資料字典的方法,將原有 19 行的方法程式碼,瞬間重構成為只有 6 行,而且讓這個類別內的程式碼變成很容易閱讀與了解他們在做甚麼,並且容易進行擴充,最重要的是,以往需要花時間來閱讀與理解的長長 Switch 敘述程式碼,也就重構不見了。
現在,我們在 StringToColor 類別中,加入一個建構函式、加入一個資料字典的欄位 ColorMaps,ColorMaps 的 是由 字串與 Color類別所組成。接著,我們會在建構式內進行 ColorMaps 這個資料字典物件的初始化動作,請把所有顏色的名稱與相對應要產生的 Color 物件敘述式,加入到這個 ColorMaps 資料字典內。
我們要重構原有的 Transfer 方法,如下列程式碼所示,在這個方法內,我們先檢查這個傳入進來的顏色字串名稱是否存在於 ColorMaps 資料字典內,若有存在的話,我們就會回傳這個顏色物件。
namespace RefactorSwitchDictionary.Refactoring
{
public class StringToColor
{
Dictionary<string, Color> ColorMaps;
public StringToColor()
{
ColorMaps = new Dictionary<string, Color>()
{
{"Red", Color.FromArgb(0xFF, 0xFF, 0x00, 0x00)},
{"Green", Color.FromArgb(0xFF, 0x80, 0x80, 0x80) },
{"Blue", Color.FromArgb(0xFF, 0x00, 0x00, 0xFF)}
};
}
public Color Transfer(string name)
{
if(!ColorMaps.ContainsKey(name))
throw new ArgumentException("不正確的顏色名稱");
return ColorMaps[name];
}
}
}
我們來看看重構之後對於 StringToColor 這個類別的用法,有沒有甚麼不同;由於我們將重構完成的 StringToColor 類別設計在 RefactorSwitchDictionary.Refactoring 命名空間之內,因此,在這裡,我們引用 StringToColor 類別的時候,將會加入 RefactorSwitchDictionary.Refactoring 命名空間到這個類別前。
您將會發現到,我們重構後的類別用法,與重構前的用法沒有不同,不過,是不是程式碼變成更加精簡與容易閱讀和維護了呢?
class Program
{
static void Main(string[] args)
{
string MyColorName = "Blue";
Console.WriteLine("使用 資料字典 來重構方法,進行 Swith 需求設計");
RefactorSwitchDictionary.Refactoring.StringToColor fooRefactoring = new RefactorSwitchDictionary.Refactoring.StringToColor();
Color fooRefactoringColor = fooRefactoring.Transfer(MyColorName);
Console.WriteLine($"{MyColorName} = A:{fooRefactoringColor.A} R:{fooRefactoringColor.R} G:{fooRefactoringColor.G} B:{fooRefactoringColor.B}");
Console.WriteLine("Press any key for continuing...");
Console.ReadKey();
}
}
執行結果內容
使用 資料字典 來重構方法,進行 Swith 需求設計
Blue = A:255 R:0 G:0 B:255
Press any key for continuing...
關於 Xamarin 在台灣的學習技術資源
歡迎加入 Xamarin 實驗室 粉絲團,在這裡,將會經常性的貼出各種關於 Xamarin / Visual Studio / .NET 的相關消息、文章、技術開發等文件,讓您可以隨時掌握第一手的 Xamarin 方面消息。
歡迎加入 Xamarin.Forms @ Taiwan,這是台灣的 Xamarin User Group,若您有任何關於 Xamarin / Visual Studio / .NET 上的問題,都可以在這裡來與各方高手來進行討論、交流。
Xamarin 實驗室 部落格 是作者本身的部落格,這個部落格將會專注於 Xamarin 之跨平台 (Android / iOS / UWP) 方面的各類開技術探討、研究與分享的文章,最重要的是,它是全繁體中文。
Xamarin.Forms 系列課程 想要快速進入到 Xamarin.Forms 的開發領域,學會各種 Xamarin.Forms 跨平台開發技術,例如:MVVM、Prism、Data Binding、各種 頁面 Page / 版面配置 Layout / 控制項 Control 的用法等等,千萬不要錯過這些 Xamarin.Forms 課程