重構:用Command替換條件調度程序

 

注:該隨筆受啓發於 《重構與模式》  第七章 第7.6小節 用Command替換條件調度程序 。ide

 

對於Command不作過多解釋,這裏我找了兩個例子、供部分園友參閱:Command例子1 Command例子2 。this

條件調度程序:我對這個名詞的理解爲,它是相對簡單的選擇結構 與 相對獨立的業務邏輯的結合體。編碼

話不是很好理解,下面舉個小例子吧。spa

 

重構前的代碼:.net

  /// <summary>
        /// 很簡單的選擇分支 一層 if else 
        /// N個 相對獨立 任務             
        /// </summary>
        /// <param name="actionName"></param>
        public void DoAction(string actionName)
        {
            if (actionName == "Action1")
            {
                // 處理 Action1任務
                Console.WriteLine("執行任務1");
            }
            else if (actionName == "Action2")
            {
                // 處理 Action2任務
                Console.WriteLine("執行任務2");
            }
            else if (actionName == "Action3")
            {
                // 處理 Action3任務
                // 無處理操做
            }

        }

 

在 《重構與模式》 一文中的重構的作法是:code

爲每個動做建立一個Command,把這些Command存儲在一個集合中, 並用獲取及執行Command的代碼替換條件邏輯。htm

重構步驟我不作詳細描述,看一下重構後的結果吧:blog

 

    public class class2
    {
        private Dictionary<string, CommandAbstract> dic;

        public class2()
        {
            this.dic = new Dictionary<string, CommandAbstract>();
            this.dic.Add("Action1", new Command1());
            this.dic.Add("Action2", new Command2());
            this.dic.Add("Action3", new Command3());
        }

        /// <summary>
        /// 應用 Command模式 替換 條件調度程序/// </summary>
        /// <param name="actionName"></param>
        public void DoAction(string actionName)
        {
            CommandAbstract command = null;

            if (dic.ContainsKey(actionName))
            {
                command = dic[actionName];
            }

            if (command != null)
            {
                command.Execute();
            }
        }
    }

    public abstract class CommandAbstract
    {
        public abstract void Execute();
    }

    public class Command1 : CommandAbstract
    {
        public override void Execute()
        {
            Console.WriteLine("執行任務1");
        }
    }

    public class Command2 : CommandAbstract
    {
        public override void Execute()
        {
            Console.WriteLine("執行任務2");
        }
    }

    public class Command3 : CommandAbstract
    {
        public override void Execute()
        {

        }
    }
  

看着 硬編碼 Dictionary 很不爽,若是常常須要添加新Command, 有可能還須要繼續重構——使其遵循開閉原則。get

方案:使用反射代替硬編碼 (簡單的Plugin模式),重構後的結果以下:string

    public static class CommandFactory
    {
        private static Dictionary<string, CommandAbstract> dic;


        static CommandFactory()
        {
            dic = new Dictionary<string, CommandAbstract>();

            Type absType = typeof(CommandAbstract);

            Assembly assem = absType.Assembly;

            foreach (Type t in assem.GetTypes())
            {
                if (t.IsClass && !t.IsAbstract && t.IsSubclassOf(absType))
                {
                    CommandAbstract command = Activator.CreateInstance(t) as CommandAbstract;

                    if (command != null && !dic.ContainsKey(command.CommandName))
                    {
                        dic.Add(command.CommandName, command);
                    }
                }
            }
        }


        public static CommandAbstract GetCommand(string commandName)
        {
            if (dic.ContainsKey(commandName))
            {
                return dic[commandName];
            }

            return null;
        }

    }


    public class class2
    {/// <summary>
        /// 重構硬編碼/// </summary>
        /// <param name="actionName"></param>
        public void DoAction(string actionName)
        {
            CommandAbstract command = CommandFactory.GetCommand(actionName);

            if (command != null)
            {
                command.Execute();
            }
        }
    }

    public abstract class CommandAbstract
    {
        public string CommandName { get; protected set; }

        public abstract void Execute();
    }

    public class Command1 : CommandAbstract
    {
        public Command1()
        {
            this.CommandName = "Action1";
        }

        public override void Execute()
        {
            Console.WriteLine("執行任務1");
        }
    }

    public class Command2 : CommandAbstract
    {
        public Command2()
        {
            this.CommandName = "Action2";
        }

        public override void Execute()
        {
            Console.WriteLine("執行任務2");
        }
    }

    public class Command3 : CommandAbstract
    {
        public Command3()
        {
            this.CommandName = "Action3";
        }

        public override void Execute()
        {

        }
    }

 

 

若是 條件表達式 較爲複雜呢,那又能夠怎樣重構?

提示:責任鏈模式。

相關文章
相關標籤/搜索