重构:用Command替换条件调度程序

 

注:该随笔受启发于 《重构与模式》  第七章 第7.6小节 用Command替换条件调度程序 。

 

对于Command不做过多解释,这里我找了两个例子、供部分园友参阅:Command例子1 Command例子2 。

条件调度程序:我对这个名词的理解为,它是相对简单的选择结构 与 相对独立的业务逻辑的结合体。

话不是很好理解,下面举个小例子吧。

 

重构前的代码:

  /// <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任务
                // 无处理操作
            }

        }

 

在 《重构与模式》 一文中的重构的做法是:

为每一个动作创建一个Command,把这些Command存储在一个集合中, 并用获取及执行Command的代码替换条件逻辑。

重构步骤我不做详细描述,看一下重构后的结果吧:

 

    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, 有可能还需要继续重构——使其遵循开闭原则。

方案:使用反射代替硬编码 (简单的Plugin模式),重构后的结果如下:

    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()
        {

        }
    }

 

 

如果 条件表达式 较为复杂呢,那又可以怎样重构?

提示:责任链模式。

 

posted @ 2015-03-12 15:52  把爱延续  阅读(697)  评论(0编辑  收藏  举报