最近又在看程杰的《大话设计模式》这本书,这真的是我超级喜欢的一本书,里面的内容很精彩,学习之余,将书中的内容整理出来,另外加上了一些自己的理解,方便日后自己回顾并同时希望本笔记可以对各位编程者有所帮助,相关技术上博主理解如有偏颇,还请指正。
简单工厂模式是项目开发中最常用也是最重要的一种设计模式,几乎在所有的项目开发中都会用到。可能你还不知道简单工厂模式是什么,但也许这种设计思想你早就在实际项目开发中接触过了。
接下来就来看看简单工厂模式到底是什么。
首先大家想一个问题,如果叫你实现一个计算器控制台程序,要求输入两个数和运算符号,得到运算结果,你会怎么做?
初级版本:
class Program { static void Main(string[] args) { try { Console.Write("请输入数字A:"); string strNumberA = Console.ReadLine(); Console.Write("请选择运算符号(+、-、*、/):"); string strOperate = Console.ReadLine(); Console.Write("请输入数字B:"); string strNumberB = Console.ReadLine(); string strResult = ""; switch (strOperate) { case "+": strResult = Convert.ToString(Convert.ToDouble(strNumberA) + Convert.ToDouble(strNumberB)); break; case "-": strResult = Convert.ToString(Convert.ToDouble(strNumberA) - Convert.ToDouble(strNumberB)); break; case "*": strResult = Convert.ToString(Convert.ToDouble(strNumberA) * Convert.ToDouble(strNumberB)); break; case "/": if (strNumberB != "0") strResult = Convert.ToString(Convert.ToDouble(strNumberA) / Convert.ToDouble(strNumberB)); else strResult = "除数不能为0"; break; } Console.WriteLine("结果是:" + strResult); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine("您的输入有错:" + ex.Message); } } }
能写出以上代码已经不错了,至少已经实现了目前的计算器功能。但是这个代码是面向过程而非面向对象的,只能满足当前的需求,程序不容易扩展和复用和维护。
试想,假如我现在又让你写一个Windows的计算器,你在原来的代码上能改吗?显然,你还需要再重新写一个程序。但是Windows计算器和控制台计算器只是在显示上不同,业务的逻辑处理是相同的。所以说你之前面向过程的程序是有弊端的:很难进行二次开发!
所以,接下来的改进之处就是利用面向对象的封装特性,将业务逻辑与界面逻辑分开,使其耦合度下降,达到复用的目的;
升级版本:
界面逻辑部分:
class Program { static void Main(string[] args) { try { Console.Write("请输入数字A:"); string strNumberA = Console.ReadLine(); Console.Write("请选择运算符号(+、-、*、/):"); string strOperate = Console.ReadLine(); Console.Write("请输入数字B:"); string strNumberB = Console.ReadLine(); string strResult = ""; strResult = Convert.ToString(Operation.GetResult(Convert.ToDouble(strNumberA),Convert.ToDouble(strNumberB),strOperate)); Console.WriteLine("结果是:" + strResult); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine("您的输入有错:" + ex.Message); } } }
业务逻辑部分:
public class Operation { public static double GetResult(double numberA,double numberB,string operate) { double result = 0d; switch (operate) { case "+": result = numberA + numberB; break; case "-": result = numberA - numberB; break; case "*": result = numberA * numberB; break; case "/": result = numberA / numberB; break; } return result; } }
以上版本代码,把业务和界面分离,如果此时再让写一个Windows应用程序的计算器,就可以复用Operation运算类了,而且不单是Windows版,Web版、手机版、Pad版都可以复用。
接下来,假如我现在希望再增加一个开根(sqrt)运算,要怎么改?你可能会想,直接在Operation里添加一个分支运算就好了。但实际项目开发中,业务逻辑通常都会很复杂,要做很多的事,不只是做个加减法这么简单。所以,我们应该保证修改某一种类型业务而不会影响其他的。比如在这里,我们应该将加减乘除等运算分离,修改其中一个而不影响另外几个,增加运算代码也不影响其他代码,这体现了面向对象的继承和多态特性。
高级版本:
/// <summary> /// 运算类 /// </summary> class Operation { private double _numberA = 0; private double _numberB = 0; /// <summary> /// 数字A /// </summary> public double NumberA { get{ return _numberA; } set{ _numberA = value;} } /// <summary> /// 数字B /// </summary> public double NumberB { get{ return _numberB; } set{ _numberB = value; } } /// <summary> /// 得到运算结果 /// </summary> /// <returns></returns> public virtual double GetResult() { double result = 0; return result; } }
</pre><pre name="code" class="csharp"> ///summary /// 加法类 /// </summary> class OperationAdd : Operation { public override double GetResult() { double result = 0; result = NumberA + NumberB; return result; } }
/// <summary> /// 减法类 /// </summary> class OperationSub : Operation { public override double GetResult() { double result = 0; result = NumberA - NumberB; return result; } }
/// <summary> /// 乘法类 /// </summary> class OperationMul : Operation { public override double GetResult() { double result = 0; result = NumberA * NumberB; return result; } }
/// <summary> /// 乘法类 /// </summary> class OperationMul : Operation { public override double GetResult() { double result = 0; result = NumberA * NumberB; return result; } }
以上,首先是一个运算类,它有两个Number属性和一个虚方法GetResult(),加减乘除都是运算类的子类,继承了它并重写了GetResult()方法,这样,修改某一个运算就不会影响其他的运算了。
那么,如何让计算器知道我们需要用哪一个方法呢?现在的问题其实就是如何去实例化对象,我们用一个单独的类来做这个创造实例的过程,这就是工厂类,
/// <summary> /// 运算类工厂 /// </summary> class OperationFactory { public static Operation createOperate(string operate) { Operation oper = null; switch (operate) { case "+": { oper = new OperationAdd(); break; } case "-": { oper = new OperationSub(); break; } case "*": { oper = new OperationMul(); break; } case "/": { oper = new OperationDiv(); break; } } return oper; } }
这样,只要输入运算符号,工厂就实例化出合适的对象,通过多态,返回父类的方法实现了计算器结果,这种方法就是简单工厂模式。
Operation oper; oper = OperationFactory.createOperate("+"); oper.NumberA = 1; oper.NumberB = 2; double result = oper.GetResult();
简单工厂模式包含以下角色和职责:
工厂(Creator):简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
抽象产品(Product):简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product):是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。
最后我们再总结一下简单工厂模式的特性:
1.产品业务逻辑与界面逻辑分开;
2.将产品细分,不同种类的产品子类都有一个共同的抽象父类,重写了父类的方法,各种产品互不干涉,修改某一个不会影响其他,并实现可可扩展;
3.增加一个工厂类Factory,该类负责根据条件选择实例化哪一种产品,并创造实例;
4.如果需要增加运算,一方面需要增加产品子类,另一方面需要修改工厂类。
好了,以上便是简单工厂模式的相关内容。