【设计模式】简单工厂模式——以一个简单的计算器为例

来源:互联网 发布:nasa直播软件 编辑:程序博客网 时间:2024/04/30 08:39

本文内容参考自《大话设计模式》(程杰 著)

注:以下代码为C#实现

1.拙劣的代码

class Program{    static void Main(string[] args)    {        Console.Write("请输入数字A:");        string A = Console.ReadLine();        Console.Write("请选择运算符号(+、-、*、/):");        string B = Console.ReadLine();        Console.Write("请输入数字B:");        string C = Console.ReadLine();        string D = "";        if (B == "+")            D = Convert.ToString(Convert.ToDouble(A) + Convert.ToDouble(C));        if (B == "-")            D = Convert.ToString(Convert.ToDouble(A) - Convert.ToDouble(C));        if (B == "*")            D = Convert.ToString(Convert.ToDouble(A) * Convert.ToDouble(C));        if (O == "/")            D = Convert.ToString(Convert.ToDouble(A) / Convert.ToDouble(C));        Console.WriteLine("结果是:" + D);    }     }

毛病:命名不规范,判断分支做多次无用功,除数为0时出错,输入不是数字……

2.规范化

class Program{    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 = "";            switch (strOperate)            {                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;            }            Console.WriteLine("结果是:" + strResult);            Console.ReadLine();        }        catch (Exception ex)        {            Console.WriteLine("您的输入有错:" + ex.Message);        }    }}

以上代码规范了,但是可重用性差!

3.业务的封装

Operation运算类

public class Operation{    public static double GetResult(double numberA, double numberB, string operate)    {        double result = 0d;        switch (operate)        {            case "+":                result = numberA + numberB;                break;            case "-":                result = numberA - numberB;                break;            case "*":                result = numberA * numberB;                break;            case "/":                result = numberA / numberB;                break;        }        return result;    }}

客户端代码

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);    }}

问题:如果我要增加其他运算,或者是想要修改运算的法则,那么其他代码都会受到影响,比如要重新编译,调试等等。

4.松耦合

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;    }}

加减乘除类

class OperationAdd : Operation{    public override double GetResult()    {        double result = 0;        result = NumberA + NumberB;        return result;    }}class OperationSub : Operation{   public override double GetResult()    {        double result = 0;        result = NumberA - NumberB;        return result;    }}class OperationMul : Operation{    public override double GetResult()    {        double result = 0;        result = NumberA * NumberB;        return result;    }}class OperationDiv : Operation{    public override double GetResult()    {        double result = 0;        if (NumberB==0)            throw new Exception("除数不能为0。");        result = NumberA / NumberB;        return result;    }}

在这里,我们定义了一个虚函数,然后其他运算继承操作类并实现该函数,这样子,如果要增加其他运算,只需要增加一个类来继承操作类就可以了,而且单个操作的修改完全不影响其他的运算!

5.简单工厂模式

使用上面代码之后,我们在客户端需要实例化相应的类,比如‘+’操作需要实例化OperationAdd,减操作需要实例化OperationSub,这样子暴露给客户的信息太多了,客户必须知道每个操作它对应的类!

使用简单的工厂模式可以避免这个问题:
简单运算工厂类

public class OperationFactory{    public static Operation createOperate(string operate)    {        Operation oper = null;        switch (operate)        {            case "+":                oper = new OperationAdd();                break;            case "-":                oper = new OperationSub();                break;            case "*":                oper = new OperationMul();                break;            case "/":                oper = new OperationDiv();                break;        }        return oper;    }}

客户端代码

Operation oper;oper = OperationFactory.createOperate(“+”);oper.NumberA = 1;oper.NumberB = 2;double result = oper.GetResult();

如果一来,客户端就简化了很多,它只需要知道 OperationFactory,并通过createOperate传入相应的操作就可以了!

当我们需要修改加法运算时,只需要修改OperationAdd,当我们需要增加其他运算时,只需要增加相应的运算子类,并在运算类工厂中增加分支即可。

同时,界面显示和我们的业务逻辑也是分离的~

UML图:
这里写图片描述

1 0
原创粉丝点击