你的位置:首页 > ASP.net教程

[ASP.net教程]设计模式(一) 简单工厂模式


1. 面向过程的计算器

static void Main(string[] args){  //面向过程的计算器  try  {    Console.WriteLine("请输入数字A: ");    string strNumA = Console.ReadLine();    Console.WriteLine("请选择运算符号(+、-、*、/): ");    string strOperate = Console.ReadLine();    Console.WriteLine("请输入数字B: ");    string strNumB = Console.ReadLine();    string strResult = string.Empty;    switch (strOperate)    {      case "+":        strResult = (Double.Parse(strNumA) + Double.Parse(strNumB)).ToString();        break;      case "-":        strResult = (Double.Parse(strNumA) - Double.Parse(strNumB)).ToString();        break;      case "*":        strResult = (Double.Parse(strNumA) * Double.Parse(strNumB)).ToString();        break;      case "/":        if (Double.Parse(strNumB) == 0)        {          throw new Exception("被除数不能为0!");        }        strResult = (Double.Parse(strNumA) / Double.Parse(strNumB)).ToString();        break;      default:        throw new Exception("运算符输入错误!");    }    Console.WriteLine(strNumA + " " + strOperate + " " + strNumB + " = " + strResult);  }  catch (Exception ex)  {    Console.WriteLine("您输入的有错:" + ex.Message);  }  Console.ReadKey();}

思考:

上面的计算器是Console版的,如果我要实现WinForm版、Web版、手机版。那怎么办呢?

Ctrl-C, Ctrl-V是一种方法(我刚写代码的时候就是这么办的)。但是当重复的代码多了,维护起来,可能就是一场灾难。

这时面向对象的优势就体现出来了,把计算器的功能封装成一个计算器类,供Console, WinForm, Web等调用。将来要维护,只维护这一个类即可。

2. 面向对象1: 封装 - 将计算和显示分开

//业务的封装 - 计算public class Operation{  public static double CalcResult(double numA, double numB, string op)  {    double result = 0d;    switch (op)    {      case "+":        result = numA + numB;        break;      case "-":        result = numA - numB;        break;      case "*":        result = numA * numB;        break;      case "/":        if (numB == 0)        {          throw new Exception("被除数不能为0!");        }        result = numA / numB;        break;      default:        throw new Exception("运算符输入错误!");    }    return result;  }}//客户端代码 - 界面static void Main(string[] args){  try  {    Console.WriteLine("请输入数字A: ");    string strNumA = Console.ReadLine();    Console.WriteLine("请选择运算符号(+、-、*、/): ");    string strOperate = Console.ReadLine();    Console.WriteLine("请输入数字B: ");    string strNumB = Console.ReadLine();    string strResult = Operation.CalcResult(double.Parse(strNumA), double.Parse(strNumB), strOperate).ToString();    Console.WriteLine(strNumA + " " + strOperate + " " + strNumB + " = " + strResult);  }  catch (Exception ex)  {    Console.WriteLine("您输入的有错:" + ex.Message);  }  Console.ReadKey();}

思考:

如果现在要加一个平方根运算,怎么办?看来只能改Operation类了,那么已经写好的加减乘除运算代码是不是也会暴露出来,面临着被误修改的风险(如果这个类是计算工资的类,那风险得多大)。而且添加完平方根后,整个类都要重新编译,岂不是很麻烦。

看来上面的实现扩展性和灵活性还是不够好,需要再设计一下。

3. 面向对象2:封装、继承、多态 - 简单工厂模式

/// <summary>/// 抽象类:运算类/// </summary>public class Operation{  private double _numA = 0;  private double _numB = 0;  public double NumA  {    get { return _numA; }    set { _numA = value; }  }  public double NumB  {    get { return _numB; }    set { _numB = value; }  }  public virtual double GetResult()  {    return 0;  }}/// <summary>/// 加法 : 继承运算类/// </summary>public class OperationAdd : Operation{  public override double GetResult()  {    return NumA + NumB;  }}/// <summary>/// 减法 : 继承运算类/// </summary>public class OperationSub : Operation{  public override double GetResult()  {    return NumA - NumB;  }}/// <summary>/// 乘法 : 继承运算类/// </summary>public class OperationMul : Operation{  public override double GetResult()  {    return NumA * NumB;  }}/// <summary>/// 除法 : 继承运算类/// </summary>public class OperationDiv : Operation{  public override double GetResult()  {    if (NumB == 0)      throw new Exception("被除数不能为0");    else      return NumA / NumB;  }}/// <summary>/// 工厂 : 生产计算器/// </summary>public class OperationFactory{  public static Operation createOperation(string op)  {    Operation oper = null;    switch (op)    {      case "+":        oper = new OperationAdd();        break;      case "-":        oper = new OperationSub();        break;      case "*":        oper = new OperationMul();        break;      case "/":        oper = new OperationDiv();        break;      default:        throw new Exception("操作符错误,只支持+-*/四则运算。");    }    return oper;  }}/// <summary>/// 客户端/// </summary>/// <param name="args"></param>static void Main(string[] args){  try  {    Console.WriteLine("请输入数字A: ");    string strNumA = Console.ReadLine();    Console.WriteLine("请选择运算符号(+、-、*、/): ");    string strOperate = Console.ReadLine();    Console.WriteLine("请输入数字B: ");    string strNumB = Console.ReadLine();    Operation oper = OperationFactory.createOperation(strOperate);    oper.NumA = double.Parse(strNumA);    oper.NumB = double.Parse(strNumB);    string strResult = oper.GetResult().ToString();    Console.WriteLine(strNumA + " " + strOperate + " " + strNumB + " = " + strResult);  }  catch (Exception ex)  {    Console.WriteLine("您输入的有错:" + ex.Message);  }  Console.ReadKey();}

思考:

现在的计算器通过封装、继承、多态把程序的耦合度降低,更加的灵活,容易修改,易于服用。

4. 简单工厂模式的UML类图

image

 

----

参考文献:《大话设计模式》 程杰 著