简单工厂设计模式(计算器实例优化)
介绍
本文内容引用自《大话这设计模式》这本书第一章节简单工厂设计模式,供自己提高代码水平使用。
案例也同样采用计算器功能实现方式展开
实现功能---->封装---->继承---->多态---->面向对象
为什么采用面向对象编程而不是面向过程呢?
在当今互联网开发的大型企业中你会发现,当你接到一个功能模块的时候不会给你完整的项目源码,特别是核心的东西,为什么呢?
仔细想一下,如果公司把员工薪资分发系统让你修改,这时你动了一下坏心思,做了一层 If 判断,如果名字是自己的话薪资*2,是不是公司就赔了?况且公司也不会这么傻,把这种核心的功能让新手做修改,这就引入代码的面向对象,将代码分为逻辑层和业务层分开处理,这样不仅逻辑清晰方便后期的修改,也方便了公司为自身的保护。
实例讲解
我们创建一个主控制台,先用一个面向过程的编程方式去写一个计算器功能,代码如下
csharp
while (true)
{
try
{
Console.WriteLine("请输入第一个数字一");
double number1 = double.Parse(Console.ReadLine());
Console.WriteLine("请输入运算符");
string symbol = Console.ReadLine();
Console.WriteLine("请输入第一个数字二");
double number2 = double.Parse(Console.ReadLine());
switch (symbol)
{
case "+":
Console.WriteLine(number1 + number2);
break;
case "-":
Console.WriteLine(number1 - number2);
break;
case "*":
Console.WriteLine(number1 * number2);
break;
case "/":
if (number2 == 0d)
{
Console.WriteLine("被除数不能为0");
break;
}
Console.WriteLine(number1 / number2);
break;
default:
break;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
这时候我们分析一下
- 首先逻辑是没有问题的,如果后期修改怎么办?是否需要将完整的代码拿出来修改?
- 如果我们后期需要增加一个开平方根,时候会影响了其他运算的逻辑?
- 如果我们现在需要开发另外一个平台的计算器功能,我们能都将这个代码拿过去直接复用?
先回答第一个问题,这个代码比较简单,修改起来也比较方便,但是如果项目需求比较大,我们可能会话费很长时间去找当时写的代码,这时候会非常话费时间,那么我们可以将逻辑层和业务层分开,代码如下
业务层划分出来
csharp
public class Operation
{
public static double GetResult(double number1,double number2,string symbol)
{
double result = 0;
switch (symbol)
{
case "+":
result = number1 + number2;
break;
case "-":
result = number1 - number2;
break;
case "*":
result = number1 * number2;
break;
case "/":
if (number2 == 0d)
{
Console.WriteLine("被除数不能为0");
break;
}
result = number1 / number2;
break;
default:
break;
}
return result;
}
}
逻辑层
csharp
while (true)
{
try
{
Console.WriteLine("请输入第一个数字一");
double number1 = double.Parse(Console.ReadLine());
Console.WriteLine("请输入运算符");
string symbol = Console.ReadLine();
Console.WriteLine("请输入第一个数字二");
double number2 = double.Parse(Console.ReadLine());
double result = Operation.GetResult(number1,number2,symbol);
Console.WriteLine("结果为"+result);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
这时候是否显得比较整洁,之后修改的时候我们直接使用Operation这个脚本修改即可
回答第二个问题
如果这时候我们需要增加一个需求,当我们做➕法运算的时候,我们得到的值始终是要多➕2的,这时候我们如果按照当前的方法修改的话,我们需要改动Operation这个类中的GetResult方法即可,但是这个方法里面包含了4个逻辑算式,如果这时候不小心动了其他的怎么办?所以这时候我们就要引入面向对象知识,封装,继承,多态的方式去修改当前代码。代码如下
csharp
public class Operation
{
private double m_number1;
private double m_number2;
public double Number1 { get { return m_number1; } set { m_number1 = value; } }
public double Number2 { get { return m_number2; } set { m_number2 = value; } }
public virtual double GetResult()
{
double result = 0;
return result;
}
}
public class Add : Operation
{
public override double GetResult()
{
double result = Number1 + Number2;
return result;
}
}
public class Subtract : Operation
{
public override double GetResult()
{
double result = Number1 - Number2;
return result;
}
}
public class Multiply : Operation
{
public override double GetResult()
{
double result = Number1 * Number2;
return result;
}
}
public class Divide : Operation
{
public override double GetResult()
{
if(Number2 == 0)
throw new Exception("除数不能为0");
double result = Number1 / Number2;
return result;
}
}
继承
修改业务层层,增加两个属性,并且重写一个方法,在定义四个不同的运算符类,分别继承业务层Operation,根据不同的方式重写基类方法
这里回答第三个问题
如何复用我们当前写的东西呢?这里可能对于刚开始编程的人来说不会区分对象,这里我们将每一个运算式分别定义一个对象,然后这里的每一个对象分别有两个属性,数字一和数字二,这样理解就比较清晰,既然明白了对象,我们就将面向对象的多态 和简单工厂设计模式引入到里面,从而达到我们所写代码的复用性,代码如下:
简单工厂:(多态)
csharp
public static Operation CreateOperation(string symbol)
{
Operation oper = null;
switch (symbol)
{
case "+":
oper = new Add();
break;
case "-":
oper = new Subtract();
break;
case "*":
oper = new Multiply();
break;
case "/":
oper = new Divide();
break;
default:
break;
}
return oper;
}
业务层:(解耦合)
csharp
public class Operation
{
private double m_number1;
private double m_number2;
public double Number1 { get { return m_number1; } set { m_number1 = value; } }
public double Number2 { get { return m_number2; } set { m_number2 = value; } }
public virtual double GetResult()
{
double result = 0;
return result;
}
}
public class Add : Operation
{
public override double GetResult()
{
double result = Number1 + Number2;
return result;
}
}
public class Subtract : Operation
{
public override double GetResult()
{
double result = Number1 - Number2;
return result;
}
}
public class Multiply : Operation
{
public override double GetResult()
{
double result = Number1 * Number2;
return result;
}
}
public class Divide : Operation
{
public override double GetResult()
{
if(Number2 == 0)
throw new Exception("除数不能为0");
double result = Number1 / Number2;
return result;
}
}
主控制台
csharp
class Program
{
static void Main(string[] args)
{
while (true)
{
try
{
Console.WriteLine("请输入第一个数字一");
double number1 = double.Parse(Console.ReadLine());
Console.WriteLine("请输入运算符");
string symbol = Console.ReadLine();
Console.WriteLine("请输入第一个数字二");
double number2 = double.Parse(Console.ReadLine());
Operation oper;
oper = OperationFactory.CreateOperation(symbol);
oper.Number1 = number1;
oper.Number2 = number2;
Console.WriteLine("结果为"+oper.GetResult());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
总结
巧妙的使用面向对象的封装继承和多态会让我们后期的维护节约不少时间,提高了开发的效率,当我们将代码移植到别的平台的时候,我们只需要将业务层Operation 和 OperationFactory移植即可方便调用。