注:该随笔受启发于 《重构与模式》  第七章 第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()
{ }
}

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

提示:责任链模式。

重构:用Command替换条件调度程序的更多相关文章

  1. 重构第四天 : 用多态替换条件语句(if else & switch)

    面相对象的一个核心基础就是多态,当你要根据对象类型的不同要做不同的操作的时候,一个好的办法就是采用多态,把算法封装到子类当中去. 重构前代码: public abstract class Custom ...

  2. 重构与模式 (Joshua Kerievsky 著)

    第1章 本书的写作缘由 第2章 重构 第3章 模式 第4章 代码坏味 第5章 模式导向的重构目录 第6章 创建 第7章 简化 第8章 泛化 第9章 保护 第10章 聚集操作 第11章 实用重构 参考文 ...

  3. 如何解决代码中if…else 过多的问题

    前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...

  4. 你还在 if...else?代码这样写才好看!

    前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...

  5. 如何解决代码中if/else 过多的问题

    前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...

  6. 重构与模式(Refactoring to Patterns)-读书笔记

    第一章 ☛过度设计:是指代码的灵活性和复杂性超出所需. 第二章 ☛重构是一种保持行为的转换. 第三章 ☛每一个模式都是由三部分组成的规则,他表达的是某一环境,一个问题以及解决问题的方案之间的关系. ☛ ...

  7. C#重构之道

    定义 重构的定义:在不改变软件可观察行为的前提下,改善其内部结构. 其中,不改变软件行为,是重构最基本的要求.要想真正发挥威力,就必须做到“不需了解软件行为”. 如果一段代码能让你容易了解其行为,说明 ...

  8. 《Code Complete》ch.24 重构

    WHAT? 重构(refactoring),Martin Fowler将其定义为“在不改变软件外部行为的前提下,对其内部结构进行改变,使之更容易理解并便于修改”. WHY? 神话:一个管理很完善的软件 ...

  9. 重构:越来越长的 switch ... case 和 if ... else if ... else

    在代码中,时常有就一类型码(Type Code)而展开的如 switch ... case 或 if ... else if ... else 的条件表达式.随着项目业务逻辑的增加及代码经年累月的修改 ...

随机推荐

  1. Form认证的几点说明

    有的页面需要用户认证之后才可以进入,通常都是在Filter的OnActionExecuting方法中我们需要获取当前用户.有两种情况不必登录:1.用户是登录的,也就是认证过的.2.用户上次登录了,但没 ...

  2. FusionCharts简单教程(三)-----如何自定义图表上的工具提示

    最近有蛮多人总是问我这个FusionCharts制表的问题,帮助他们解决之后,在昨晚发现以前整理的笔记中有这个简单教程,而且以前也发表了几篇这个博文,所以就将其全部上传上来供别人参考.如有不正确之处望 ...

  3. java提高篇(二十)-----集合大家族

          在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的Arra ...

  4. 浅谈Excel开发:六 Excel 异步自定义函数

    上文介绍了Excel中的自定义函数(UDF ),它极大地扩展了Excel插件的功能,使得我们可以将业务逻辑以Excel函数的形式表示,并可以根据这些细粒度的自定义函数,构建各种复杂的分析报表. 普通的 ...

  5. C# socket编程实践——支持广播的简单socket服务器

    在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# socket编程基本知识,写一个支持广播的简单server/clie ...

  6. Lucene系列-分析器

    分析器介绍 搜索的基础是对文本信息进行分析,Lucene的分析工具在org.apache.lucene.analysis包中.分析器负责对文本进行分词.语言处理得到词条,建索引和搜索的时候都需要用到分 ...

  7. 在Windows下安装Memcached

    Windows下的Memcache安装: 需要运行命令行工具cmd 请以管理员权限运行 开始->附件->命令提示符,以管理员身份运行 假如当前C:\windows\system32,输入c ...

  8. JavaScript函数后面加不加括号的区别

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  9. JSP连接mysql数据库的重点

    1:用mysql驱动把mysql与tomcat的连接起来.把mysql驱动包(不用解压)放到Tomcat安装目录中lib文件夹下即可. 2:然后在自己的新建的web应用程序上面就可以下下面的代码 3: ...

  10. SeaJS与RequireJS最大的区别

    SeaJS与RequireJS最大的区别 U_U 2013-06-20 16:21:12 执行模块的机制大不一样-----------------------------------由于 Requir ...