设计模式笔记(1)简单工厂模式
最近在看程杰的《大话设计模式》,在这里做一点笔记。
书中主要有两个角色:
小菜:初学者,学生;
大鸟:小菜表哥,大佬。
也按图中的对话形式
01 简单工厂模式
要求:使用c++、Java、C#或VB.NET任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果。
小菜的代码:
大鸟指出部分问题:
- A, B, C, D 这样的命名不规范;
- if的判断分支,逻辑有误,且未考虑除数输入为0/输入为字符非数字等等。
小菜对代码进行修改:
修改后的逻辑基本没有问题了,但是并没有面向对象。
如何设计出容易维护,容易扩展,又容易复用的计算器程序呢?
程序要避免重复。
小菜:那就是分类,将计算和显示分开?
大鸟:准确说,是让业务逻辑与界面逻辑分开,让它们之间的耦合度下降。只有分离开,才可以达到容易维护或扩展。
接下来,小菜重新进行了尝试:
运算类:
main函数:
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);}
}
目前,无论在windows,还是在web,手机端都可以在需要运算时使用上面运算类的定义。
这里使用到的是“面向对象”的封装。
提问:如何更灵活的修改和扩展代码呢?比如,现在希望增加一个开根号(sqrt)的运算。
小菜:直接修改Operation类?
大鸟:但问题是,要加一个平方根运算,却需要让加减乘除的运算都得来参与编译。而且还可能让原有的运行良好的功能代码产生了变化,这个风险太大了
因此,需要尽量把加减乘除等运算分离,修改其中一个不影响其他
小菜进行新尝试:
operation运算类:
public class Operation
{private double _numberA = 0;private double _numberB = 0;public double NumberA{get { return _numberA; }set { _numberA = value; }}public double NumberB{get { return _numberB; }set { _numberB = value; }}public virtual double GetResult(){double result = 0;return result;}
}
两个Number属性,主要用于计算器的前后数,然后有一个虚方法GetResult(),用于得到结果。
加减乘法类:
加减乘除都写成了运算类的子类,继承它后,重写了GetResult()方法,这样如果要修改任何一个算法,就不需要提供其他算法的代码了。
但是,如何让计算器知道我是希望用哪一个算法呢?
考虑用一个单独的类来做这个创造实例的过程,这就是“工厂”
进行如下设置:
此时,只需要输入运算符号,工厂就实例化出合适的对象。
一个实例:
Operation oper;
oper = OperationFactory.createOperate(“+”);
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult();
此时,例如要修改加法运算,改OperationAdd即可。
如果需要增加各种复杂运算,增加相应的运算子类,并在switch中增加分支。