使用简单工厂和分层的思想对winform计算器项目进行了实践(项目代码见后期分享),在写工厂代码的时候用到了switch case语句对具体的计算方法进行了实例化代码如下
class OperateFactory
{
public static Operate CreateOperate(string oper)
{
Operate operate = null;
switch (oper)
{
case "+":
operate = new AddOperate();
break;
case "-":
operate = new MinusOperate();
break;
case "*":
operate = new MutiplyOperate();
break;
case "/":
operate = new DivideOperate();
break;
}
return operate;
}
}
从扩展性的角度来说,当增加新的算法时首先要增加一个算法类,然后必须在工厂里加一条case语句,这就破坏了开闭原则,使代码可维护性降低。所以需要将switch语句抽离出来——这就需要用到反射机制了。
修改类不符合开闭原则,但修改配置文件不会对类进行破坏啊。下面来看怎么通过反射机制来使switch语句更优雅。
首先需要把case的内容写到配置文件里,这样就不用再修改类了(关于配置文件见后期分享)代码如下
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!--读取算法类的上一级路径-->
<!--我将算法类放在了类库里-->
<connectionStrings>
<add name="DAL" connectionString="DAL" />
</connectionStrings>
<!--可配置运算符-->
<!--用键值对的方式将运行时用到的算符和算法类的类名绑定-->
<appSettings>
<add key ="+" value="AddOperate"/>
<add key ="-" value="MinusOperate"/>
<add key ="*" value="MutiplyOperate"/>
<add key ="/" value="DivideOperate"/>
</appSettings>
</configuration>
将case语句里的东西抽离并放到了配置文件里,接下来就要在工厂里调用配置文件来替换掉switch语句了(涉及到配置文件的操作,可去了解一下)。因为在这里用了反射机制和对配置文件的操作,所以对于工厂这个类需要做些前期准备:
在工厂类所属路径下右击“引用”,点击“添加引用”,将程序集引用进来,如图
然后引用命名空间,如图
做好了充足的准备,接下来就可以对工厂进行改造,建一个优雅的工厂了,代码如下
public class OperateFactory
{
public static Operate CreateOperate(string oper)
{
Operate operate = null;
//通过“DAL"这个配置文件里定义好的名来读取算法类所在程序集
string dalName = ConfigurationManager.ConnectionStrings["DAL"].ToString();
//读取配置文件中的键,以获得算法类的值
string fullName = ConfigurationManager.AppSettings[oper];
//将程序集点儿类名拼接成字符串
string className = dalName+"."+fullName;
//通过反射实例化出拼接好的字符串点儿出来的类
Assembly assembly = Assembly.Load(dalName);
operate = (Operate)assembly.CreateInstance(className);
return operate;
}
}
这样,工厂只负责读取配置文件并通过反射来实例化类,具体实例化哪些类就不是它所关心的事儿了,我们已将具体需要实例化的类放到了配置文件里,从而在不破坏类的前提下对算法进行扩展。
不得不感叹一下:”反射反射,程序员的快乐“啊。