標籤:star rtc style .exe bre drive 元素 帶來 default
建議104:用多態代替條件陳述式
假設要開發一個自動駕駛系統。在設計之初,此自動駕駛系統擁有一個駕駛系統命令的枚舉類型:
enum DriveCommand { Start, Stop }
當前該枚舉存在兩個命令:開始、停止。又假設有一個駕駛方法可以處理車輛接收到的指令。一開始我們可能像下面這樣編碼:
static void Main(string[] args) { DriveCommand command = DriveCommand.Start; Drive(command); command = DriveCommand.Stop; Drive(command); } static void Drive(DriveCommand command) { if (command == DriveCommand.Start) { //車輛啟動 } else if (command == DriveCommand.Stop) { //車輛停止 } }
有些人可能喜歡用switch語句(當然,switch本質上也是if語句)。
static void Drive(DriveCommand command) { switch (command) { case DriveCommand.Start: //車輛啟動 break; case DriveCommand.Stop: //車輛停止 break; default: break; } }
隨著更多的系統功能不斷地被開發出來,我們考慮為車輛加入的命令也越來越多,如下所示:
enum DriveCommand { Start, Stop, Pause, TurnLeft, TurnRight }
隨著DriveCommand元素的增加,採用if或switch語句將帶來可怕的混亂狀態是顯而易見的。在一個複雜的控制系統中,命令可能會多達上百條。每增加一條命,我們首先要修改Drive方法。Drive方法將會及其膨脹,而且每行代碼幾乎是一模一樣的:
if 命令
then 行動
這種情況,我們不得不考慮重構原來的代碼。原來的設計理念也是欠妥當的,它不遵守設計模式中的“開閉原則”。開閉原則是指:對擴充開發,對修改關閉。遵從開閉原則的一次重構是,使用多態來規避不斷膨脹的條件陳述式。首先,設計一個抽象類別Commander:
abstract class Commander { public abstract void Execute(); }
所有的Start或者Stop之類的命令,全部繼承自這個抽象類別:
class StartCommander : Commander { public override void Execute() { //啟動 } } class StopCommander : Commander { public override void Execute() { //停止 } }
在使用多態後,調用方法的代碼應該如下所示:
static void Main(string[] args) { Commander commander = new StartCommander(); Drive(commander); commander = new StopCommander(); Drive(commander); } static void Drive(Commander commander) { commander.Execute(); }
可見,代碼簡潔了不少,而且,可擴充性增強了。即使未來還需要增加命令,擴充相應的子類就可以了。而且我們關閉了修改,即對Drive方法,即使增加再多的命令,也不需要對其進行修改。
轉自:《編寫高品質代碼改善C#程式的157個建議》陸敏技
【轉】編寫高品質代碼改善C#程式的157個建議——建議104:用多態代替條件陳述式