码迷,mamicode.com
首页 > Windows程序 > 详细

简单工厂模式 - 怎样实现高逼格的计算器(C#)

时间:2015-12-26 13:26:38      阅读:302      评论:0      收藏:0      [点我收藏+]

标签:

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类图

技术分享

 

----

参考文献:《大话设计模式》第1章

简单工厂模式 - 怎样实现高逼格的计算器(C#)

标签:

原文地址:http://www.cnblogs.com/chrisjjc/p/5077894.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!