重构:用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()
{ }
}
如果 条件表达式 较为复杂呢,那又可以怎样重构?
提示:责任链模式。
重构:用Command替换条件调度程序的更多相关文章
- 重构第四天 : 用多态替换条件语句(if else & switch)
面相对象的一个核心基础就是多态,当你要根据对象类型的不同要做不同的操作的时候,一个好的办法就是采用多态,把算法封装到子类当中去. 重构前代码: public abstract class Custom ...
- 重构与模式 (Joshua Kerievsky 著)
第1章 本书的写作缘由 第2章 重构 第3章 模式 第4章 代码坏味 第5章 模式导向的重构目录 第6章 创建 第7章 简化 第8章 泛化 第9章 保护 第10章 聚集操作 第11章 实用重构 参考文 ...
- 如何解决代码中if…else 过多的问题
前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...
- 你还在 if...else?代码这样写才好看!
前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...
- 如何解决代码中if/else 过多的问题
前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...
- 重构与模式(Refactoring to Patterns)-读书笔记
第一章 ☛过度设计:是指代码的灵活性和复杂性超出所需. 第二章 ☛重构是一种保持行为的转换. 第三章 ☛每一个模式都是由三部分组成的规则,他表达的是某一环境,一个问题以及解决问题的方案之间的关系. ☛ ...
- C#重构之道
定义 重构的定义:在不改变软件可观察行为的前提下,改善其内部结构. 其中,不改变软件行为,是重构最基本的要求.要想真正发挥威力,就必须做到“不需了解软件行为”. 如果一段代码能让你容易了解其行为,说明 ...
- 《Code Complete》ch.24 重构
WHAT? 重构(refactoring),Martin Fowler将其定义为“在不改变软件外部行为的前提下,对其内部结构进行改变,使之更容易理解并便于修改”. WHY? 神话:一个管理很完善的软件 ...
- 重构:越来越长的 switch ... case 和 if ... else if ... else
在代码中,时常有就一类型码(Type Code)而展开的如 switch ... case 或 if ... else if ... else 的条件表达式.随着项目业务逻辑的增加及代码经年累月的修改 ...
随机推荐
- Form认证的几点说明
有的页面需要用户认证之后才可以进入,通常都是在Filter的OnActionExecuting方法中我们需要获取当前用户.有两种情况不必登录:1.用户是登录的,也就是认证过的.2.用户上次登录了,但没 ...
- FusionCharts简单教程(三)-----如何自定义图表上的工具提示
最近有蛮多人总是问我这个FusionCharts制表的问题,帮助他们解决之后,在昨晚发现以前整理的笔记中有这个简单教程,而且以前也发表了几篇这个博文,所以就将其全部上传上来供别人参考.如有不正确之处望 ...
- java提高篇(二十)-----集合大家族
在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的Arra ...
- 浅谈Excel开发:六 Excel 异步自定义函数
上文介绍了Excel中的自定义函数(UDF ),它极大地扩展了Excel插件的功能,使得我们可以将业务逻辑以Excel函数的形式表示,并可以根据这些细粒度的自定义函数,构建各种复杂的分析报表. 普通的 ...
- C# socket编程实践——支持广播的简单socket服务器
在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# socket编程基本知识,写一个支持广播的简单server/clie ...
- Lucene系列-分析器
分析器介绍 搜索的基础是对文本信息进行分析,Lucene的分析工具在org.apache.lucene.analysis包中.分析器负责对文本进行分词.语言处理得到词条,建索引和搜索的时候都需要用到分 ...
- 在Windows下安装Memcached
Windows下的Memcache安装: 需要运行命令行工具cmd 请以管理员权限运行 开始->附件->命令提示符,以管理员身份运行 假如当前C:\windows\system32,输入c ...
- JavaScript函数后面加不加括号的区别
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- JSP连接mysql数据库的重点
1:用mysql驱动把mysql与tomcat的连接起来.把mysql驱动包(不用解压)放到Tomcat安装目录中lib文件夹下即可. 2:然后在自己的新建的web应用程序上面就可以下下面的代码 3: ...
- SeaJS与RequireJS最大的区别
SeaJS与RequireJS最大的区别 U_U 2013-06-20 16:21:12 执行模块的机制大不一样-----------------------------------由于 Requir ...