• 重构:用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()
            {
    
            }
        }

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

    提示:责任链模式。

  • 相关阅读:
    JAVA第一次上机作业
    如何设置FreePBX的数据库用户可以通过远程来连接Mysql数据库?
    Mysql 用户root密码重置
    使用FreePBX和第三方线路对接
    防御攻击
    Xshell配置公钥,免密码登陆
    centos7防火墙启动关闭
    Windows执行bat脚本乱码
    Windows开机执行bat脚本
    bat脚本之启动MySQL服务
  • 原文地址:https://www.cnblogs.com/08shiyan/p/4332638.html
Copyright © 2020-2023  润新知