zoukankan      html  css  js  c++  java
  • 简单工厂模式(2)

    一、举例

    用控制台程序做一个非常简单的计算机,实现加减乘除运算即可,那么,大家自然而然的会写出如下代码

     1 static void Main(string[] args)
     2         {
     3             Console.WriteLine("请输入数字A:");
     4             string strNumA = Console.ReadLine();
     5             Console.WriteLine("请选择运算符号(+、-、*、、)");
     6             string strOperate = Console.ReadLine();
     7             Console.WriteLine("请输入数字C:");
     8             string strNumB = Console.ReadLine();
     9             string strResult = "";
    10             if (strOperate == "+")
    11             {
    12                 strResult = Convert.ToString(Convert.ToDouble(strNumA) + Convert.ToDouble(strNumB));
    13             }
    14             if (strOperate == "-")
    15             {
    16                 strResult = Convert.ToString(Convert.ToDouble(strNumA) - Convert.ToDouble(strNumB));
    17             }
    18             if (strOperate == "*")
    19             {
    20                 strResult = Convert.ToString(Convert.ToDouble(strNumA) * Convert.ToDouble(strNumB));
    21             }
    22             if (strOperate == "/")
    23             {
    24                 strResult = Convert.ToString(Convert.ToDouble(strNumA) / Convert.ToDouble(strNumB));
    25             }
    26             Console.WriteLine($"结果是:{strResult}");
    27             Console.ReadKey();
    28         }

    二、演绎

    1、第一步演绎

    ①由于在判断运算符时,用的是if语句,这意味着每个条件都需要做判断,相当于计算机做了三次无用功。

    ②没有输入校验,例如,除数不能为零的问题等等

    就上述两个问题,做如下修改:(输入校验此处先只做除数为零的校验)

     1 static void Main(string[] args)
     2         {
     3             Console.WriteLine("请输入数字A:");
     4             string strNumA = Console.ReadLine();
     5             Console.WriteLine("请选择运算符号(+、-、*、、)");
     6             string strOperate = Console.ReadLine();
     7             Console.WriteLine("请输入数字C:");
     8             string strNumB = Console.ReadLine();
     9             string strResult = "";
    10             switch (strOperate)
    11             {
    12                 case "+":
    13                     strResult = Convert.ToString(Convert.ToDouble(strNumA) + Convert.ToDouble(strNumB));
    14                     break;
    15                 case "-":
    16                     strResult = Convert.ToString(Convert.ToDouble(strNumA) - Convert.ToDouble(strNumB));
    17                     break;
    18                 case "*":
    19                     strResult = Convert.ToString(Convert.ToDouble(strNumA) * Convert.ToDouble(strNumB));
    20                     break;
    21                 case "/":
    22                     if (strNumB != "0")
    23                     {
    24                         strResult = Convert.ToString(Convert.ToDouble(strNumA) / Convert.ToDouble(strNumB));
    25                     }
    26                     else
    27                     {
    28                         strResult = "除数不能为0";
    29                     }
    30                     break;
    31             }
    32             Console.WriteLine($"结果是:{strResult}");
    33             Console.ReadKey();
    34         }

    2、第二步演绎

    ①上述写的简单的计算器仅仅体现了面向过程的编程,没有体现面向对象的编程

    ②上述代码使用控制台应用实现的,假如有一天我需要用Winform、Web 等实现一模一样的需求,那么,上述代码则需要重新编写,好可怕。

    就上述问题,做如下修改:

    将业务逻辑与界面分离

    Operation运算类

     1 public class Operation
     2     {
     3         public static double GetResult(double numA, double numB, string strOperate)
     4         {
     5             double result = 0d;
     6             switch (strOperate)
     7             {
     8                 case "+":
     9                     result = numA + numB;
    10                     break;
    11                 case "-":
    12                     result = numA - numB;
    13                     break;
    14                 case "*":
    15                     result = numA * numB;
    16                     break;
    17                 case "/":
    18                     result = numA / numB;
    19                     break;
    20             }
    21             return result;
    22         }
    23     }

    客户端

     1 static void Main(string[] args)
     2         {
     3             try
     4             {
     5                 Console.WriteLine("请输入数字A:");
     6                 string strNumA = Console.ReadLine();
     7                 Console.WriteLine("请选择运算符号(+、-、*、、)");
     8                 string strOperate = Console.ReadLine();
     9                 Console.WriteLine("请输入数字C:");
    10                 string strNumB = Console.ReadLine();
    11                 string strResult = "";
    12                 strResult = Convert.ToString(Operation.GetResult(Convert.ToDouble(strNumA), Convert.ToDouble(strNumB), strOperate));
    13                 Console.WriteLine($"结果是:{strResult}");
    14                 Console.ReadKey();
    15             }
    16             catch (Exception ex)
    17             {
    18                 Console.WriteLine($"您的输入有错:{ex.Message}");
    19             }
    20         }

    这样的话,无论是控制台,还是Winform以及其他应用,只需要调用 Operation 这个类即可了。实现了业务逻辑与界面的分离。这里,也用到了面向对象编程的三大特性之一的封装。

    3、第三步演绎

    ①如果我想增加一种计算方式,例如开根号(sqrt)运算怎么办,只能是修改Operation类,在switch中增加一种情况。

    ②针对①问题做修改的话,那么另一个问题就来了,我修改Oeration类的时候,之前写好的加减乘除功能全在其中,如果我不小心,或者有意搞破坏,将本来运行的好好的加减乘除功能改掉,怎么办?(此例中仅仅是计算器,如果换做是成熟的产品,或者涉及到资金运算等等的代码,运行的好好的,不可能会让程序员在其中胡作非为的)

    针对上述问题,作如下修改:

    我可以将加减乘除各种运算分别封装到不同的类里面,这样,就能解决②的问题,每增加一种运算,我就增加一个类,这样①问题也解决了。

    首先,将不同的运算抽象出一个共同的类,即父类

     1 public class Operation
     2     {
     3         private double _numberA = 0;
     4         private double _numberB = 0;
     5         public double NumberA
     6         {
     7             get
     8             {
     9                 return _numberA;
    10             }
    11 
    12             set
    13             {
    14                 _numberA = value;
    15             }
    16         }
    17         public double NumberB
    18         {
    19             get
    20             {
    21                 return _numberB;
    22             }
    23 
    24             set
    25             {
    26                 _numberB = value;
    27             }
    28         }
    29         public virtual double GetResult()
    30         {
    31             double result = 0;
    32             return result;
    33         }
    34     }

    其次,让不同的运算继承这个父类,然后根据不同的运算,重写父类中的GetResult方法

     1 //加法类
     2     public class OperationAdd:Operation
     3     {
     4         public override double GetResult()
     5         {
     6             double result = 0;
     7             result = NumberA + NumberB;
     8             return result;
     9         }
    10     }
    11     //减法类
    12     public class OperationSub : Operation
    13     {
    14         public override double GetResult()
    15         {
    16             double result = 0;
    17             result = NumberA = NumberB;
    18             return result;
    19         }
    20     }
    21     //乘法类
    22     public class OperationMul : Operation
    23     {
    24         public override double GetResult()
    25         {
    26             double result = 0;
    27             result = NumberA * NumberB;
    28             return result;
    29         }
    30     }
    31     //除法类
    32     public class OperationDiv : Operation
    33     {
    34         public override double GetResult()
    35         {
    36             double result = 0;
    37             if (NumberB==0)
    38             {
    39                 throw new Exception("除数不能为0");
    40             }
    41             result = NumberA / NumberB;
    42             return result;
    43         }
    44     }

    这样,上述的两个问题就迎刃而解了。

    4、第四步演绎

    到了简单工厂最核心的地方了。

     这么多的类,客户端该如何用这些类呢,换句话说,客户端如何实例化这些类呢?那么,就需要一个核心的东西——工厂,这个工厂负责给客户端提供他想要的类的实例。我想要实例化什么类,告诉工厂就可以了。

    代码如下:

     1 public class OperationFactory
     2     {
     3         public static Operation createOperate(string operate)
     4         {
     5             Operation oper = null;
     6             switch (operate)
     7             {
     8                 case "+":
     9                     oper = new OperationAdd();
    10                     break;
    11                 case "-":
    12                     oper = new OperationSub();
    13                     break;
    14                 case "*":
    15                     oper = new OperationMul();
    16                     break;
    17                 case "/":
    18                     oper = new OperationDiv();
    19                     break;
    20             }
    21             return oper;
    22         }
    23     }

    注意一点,这个工厂中的方法,返回的是加减乘除这些类的父类。

    好了,制造类实例的工厂有了,那么,客户端只需要告诉工厂,给我造一个什么类的实例,然后用这个实例就可以了。

    客户端代码如下

     1 static void Main(string[] args)
     2         {
     3             Operation oper;
     4             //告诉工厂,给我一个加法类的实例
     5             oper = OperationFactory.createOperate("+");
     6             oper.NumberA = 1;
     7             oper.NumberB = 2;
     8             double result = oper.GetResult();
     9             Console.WriteLine(result);
    10             Console.ReadKey();
    11         }

     经过上述一系列的演绎,也就形成了简单工厂模式。

    三、总结

    简单工厂模式,即 通过一个‘工厂类’,用于子类返回父类对象。


    工厂模式结束,下一次,将讲解策略模式 

  • 相关阅读:
    Luogu 1514 引水入城
    HDU 2196 Computer
    CF460C Present
    初等数论整理
    2019UMS培训day6解题报告
    2019UMS培训day5解题报告
    2019UMS培训day3解题报告
    Luogu 1731 生日蛋糕
    JavaWeb之ServletContext域对象
    c3p0连接池
  • 原文地址:https://www.cnblogs.com/xiaomowang/p/6232893.html
Copyright © 2011-2022 走看看