设计模式 ---- 简单工厂模式(一)
1、面向对象的思想
传统印刷术与活字印刷术,这就好像是面向过程和面向对象的思想,之前我们编写程序是从计算机的角度来进行编写程序,虽然,这样速度快,简洁优美,但是不容易维护,难复用,不好扩展,灵活性也不好。这就像一个刻好的印刷板一样,刷墨,放纸就行了,但是,这个板子只能做这一件事呀,
而面向对象就需要从用户的角度出发,要考虑多种情况,他们会改需求,加需求,减需求,就想一个刻好的模板,发现字不对,要改个字,加个字,或减个字,将字的顺序从左到右变成从上到下,不能每次都要动整体对吧,因为万事万物都是变化的,这就像活字印刷术一样,刻好的每个字都有用,这次不到下次也能用,可以重复使用,修改的话只需要动某个字就行了,扩展的话只需要增加某个字在放进去就行了,变换顺序,也只要将字的顺序调整一下,灵活性大大增加,而且以后维护的话也容易维护,因为直接看一段的话,肯定没有将这一段分成不同的几块后更容易理解。而且我的记忆力也不怎么出众。
将上面的话专业点就是,面向过程思想编写的程序耦合度很高,他的每一块都和整体密不可分,牵一发而动全身,将一件事分成先后顺序后,然后使用函数一个一个依次调用。
而面向对象,通过封装、继承、多态把程序的耦合度降低,在结合设计模式使程序更加的灵活,容易修改,易于复用。
注意:复制与复用
复制的话,将原来的代码改个名字在增加一次,原来的代码做的还是原来的事,导致整体代码增加
复用的话,这段代码,都可以调用, 尽量避免含有重复的代码。
一个小例子:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace obgestu { class Program { static void Main(string[] args) { try { Console.Write("请输入数字A:"); string strNumberA = Console.ReadLine(); Console.Write("请选择括号中的运算符号(+,-,*,/):"); string strSymbol = Console.ReadLine(); Console.Write("请输入数字B:"); string strNumberB = Console.ReadLine(); string strResult = string.Empty; switch (strSymbol) { 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; default: Console.WriteLine("请输入正确的符号!"); break; } Console.WriteLine("结果是:" + strResult); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine("您输入的有错,请根据提示输入!:"+ex.Message); Console.ReadLine(); } } } }
2、封装
将业务逻辑与界面逻辑分开,让他们的耦合度下降
运算类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace obgestu { class Symbol { public static string GetResult(double numberA,double numberB,string strSymbol) { string result = string.Empty; switch (strSymbol) { case "+": result =Convert.ToString(numberA + numberB); break; case "-": result = Convert.ToString(numberA - numberB); break; case "*": result = Convert.ToString(numberA * numberB); break; case "/": if (numberB == 0) { result = "除数不能是0!"; } else { result = Convert.ToString(numberA / numberB); } break; default: result = "请输入正确的符号!"; break; } return result; } } }
客户端代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace obgestu { class InputText { static void Main(string[] args) { try { Console.Write("请输入数字A:"); string strNumberA = Console.ReadLine(); Console.Write("请选择运算符号(+、-、*、/):"); string stSymbol = Console.ReadLine(); Console.Write("请输入数字B:"); string strNumberB = Console.ReadLine(); string strResult = string.Empty; strResult = Symbol.GetResult(Convert.ToDouble(strNumberA), Convert.ToDouble(strNumberB), stSymbol); Console.WriteLine("结果是:"+strResult); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine("您输入的不对:" + ex.Message); } } } }
虽然可以满足但是只用到的封装,而且分的还不够开可以再次修改为
3、封装、继承、多态
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; //运算数 namespace obgestu.model { public class Operands { 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; } } }
继承
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using obgestu.model; namespace obgestu.service { //加法类 继承 运算基类 class OperationAdd : Operands { public override double GetResult() { double result = 0; result = NumberA + NumberB; return result; } } //减法类 继承 运算基类 class OperationSubtraction : Operands { //重写虚方法 public override double GetResult() { double result = 0; result = NumberA - NumberB; return result; } } //乘法类 继承 运算基类 class OperationMultiplication : Operands { public override double GetResult() { double result = 0; result = NumberA * NumberB; return result; } } //除法类 继承 运算基类 class OperationDivide : Operands { public override double GetResult() { double result = 0; if (NumberB == 0) { throw new Exception("除数不能为0!"); }else { result = NumberA / NumberB; } return result; } } }
4、简单工厂模式
如何优雅的实例化对象,使用一个单独的类来创造实例的过程,称为工厂
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using obgestu.model; using obgestu.service; namespace obgestu { class OperationFactory { public static Operands createOperateFactory(string symbol) { Operands operands = null; switch (symbol) { case "+": operands = new OperationAdd(); break; case "-": operands = new OperationSubtraction(); break; case "*": operands = new OperationMultiplication(); break; case "/": operands = new OperationDivide(); break; default: throw new Exception("请正确输入符号!"); //break; } return operands; } } }
只需要输入运算符号,工厂就可以实例化合适的对象,通过多态,将计算的结果返回父类。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using obgestu.service; using obgestu.model; namespace obgestu { class Calculator { static void Main(string[] args) { Operands operand; //借助工厂进行实例化相应的对象 operand = OperationFactory.createOperateFactory("=="); operand.NumberA = 1; operand.NumberB = 0; double result = operand.GetResult(); Console.WriteLine("结果:" + result); Console.ReadLine(); } } }
使用vs 生成类图: