设计模式之旅-----简单工厂
小需求:实现一个简单的控制台计算器,要求根据用户输入的运算符号进行相对于的加、减、乘、除这四种运算,并且要求具有哦良好的灵活性以及扩展性。
分析:利用简单工厂模式实现。根据继承以及多态的特性,将变化的部分抽取出来,定义一个算法接口IOperator,里面定义一个运算方法OperatorResult,根据要求的运算,为每种运算创建一个继承IOperator的类;这样便于后期的扩展,并且修改一个运算也不会影响到其他的运算类。剩下的就是创建对象的事情了,然后创建一个工厂类Factory,定义一个CreateInstance方法,根据用户输入的运算符号,创建不同的运算对象。
废话不多说,贴代码...
/// <summary> /// 运算类接口,指向不同的运算实现类 /// </summary> public interface IOperator { double OperatorResult(double x,double y); }
public class AddOperator : IOperator { /// <summary> /// 加法运算类 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public double OperatorResult(double x, double y) { return x + y; } } public class DiviOperator : IOperator { /// <summary> /// 除法运算类 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public double OperatorResult(double x, double y) { if (y == 0) { throw new Exception("0不能作被除数!"); } return x / y; } } public class MultOperator : IOperator { /// <summary> /// 乘法运算类 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public double OperatorResult(double x, double y) { return x * y; } } public class SubOperator : IOperator { /// <summary> /// 减法运算类 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public double OperatorResult(double x, double y) { return x - y; } }
public class Factory { /// <summary> /// 工厂方法,根据用户需要创建不同的对象 /// </summary> /// <param name="type"></param> /// <returns></returns> public static IOperator CreateInstance(string type) { IOperator instance = null; switch(type) { case "+" : instance = new AddOperator(); break; case "-": instance = new SubOperator(); break; case "*": instance = new MultOperator(); break; case "/": instance = new DiviOperator(); break; default: break; } if(instance == null) { throw new Exception("未定义的运算符号:" + type); } return instance; } }
static void Main(string[] args) { Console.WriteLine("请输入第一个数(按enter键结束):"); string a = Console.ReadLine(); Console.WriteLine("请输入运算符号(+,-,*,/;按enter键结束):"); string opstr = Console.ReadLine(); Console.WriteLine("请输入第二个数(按enter键结束):"); string b = Console.ReadLine(); try { IOperator opera = Factory.CreateInstance(opstr);//工厂类创建对应的对象 double d1 = NumCheck(a, 1); double d2 = NumCheck(b, 1); Console.WriteLine("运算结果是:" + opera.OperatorResult(d1,d2).ToString()); }catch(Exception ex) { Console.WriteLine(ex.Message); } Console.ReadKey(); } /// <summary> /// 对用户输入的数据进行检查 /// </summary> /// <param name="num"></param> /// <param name="defaultNum"></param> /// <returns></returns> private static double NumCheck(string num,double defaultNum) { if(!double.TryParse(num, out defaultNum)) { throw new Exception("输入的不是数字:" + num); } return defaultNum; }
优点
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
这些缺点在工厂方法模式中得到了一定的克服。

浙公网安备 33010602011771号