[设计模式学习]设计模式学习之简单工厂模式

最近在看《大话设计模式》,就做了一些学习笔记。
当然语言不是问题,本文采用C#语言。
面试单位要求用任意一种面向对象语言的面向对象思想实现一个计算机控制台程序,要求输入两个数和运算符号,得到结果。
第一次写的代码如下:

class Program
{
    static void Main(String[] args)
    {
        Console.WriteLine("请输入数字A:");
        string A = Console.ReadLine();
        Console.WriteLine("请选择运算符号(+,-,*,/):");
        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(B == "/")
        {
            D = Convert.ToString(Convert.ToDouble(A) / Convert.ToDouble(C));
        }
        Console.WriteLine("结果是:" + D);
    }
}

乍一看,功能实现了,其实有很多不足之处。
1、A,B,C,D这样的命名极不规范。
2、if的判断分支,意味着每个条件都要做判断,等于计算机做了三次无用功。
3、如果除数时,用户输出了0怎么办?如果用户输入的是字符符号而不是数字怎么办?

马上改,第二次修改代码如下:

class Program
{
    static void Main(String[] args)
    {
    try
    {
        Console.WriteLine("请输入数字A:");
        string strNumberA = Console.ReadLine();
        Console.WriteLine("请选择运算符号(+,-,*,/):");
        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);
    }   
  }
}

大功告成了?别忘了出题人说的是面向对象,这里没有面向对象的思想。我们碰到问题总是直觉的用计算机能够理解的逻辑思维来描述和表达解决的问题及具体的求解过程。这样的思维使得我们的程序使得我们的程序只为满足实现当前的需求,程序不容易维护,不容易扩展,更不容易复用。从而达不到高质量代码的要求。

我们可以考虑通过封装,继承,多态把程序的耦合度降低。如果公司要求你再写一个Windows的计算器,如何复用代码呢?最好是让业务逻辑和界面逻辑分开,让他们之间的耦合度降低。
Operator运算类

public class Operation
{
    public static double GetResult(double numberA, double numberB, string operator)
    {
        double result = 0d;
        switch(operator)
        {
            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.WriteLine("请输入数字A:");
        string strNumberA = Console.ReadLine();
        Console.WriteLine("请选择运算符号(+,-,*,/):");
        string strOperate = Console.ReadLine();
        Console.Write("请输入数字B:");
        string strNumberB = Console.ReadLine();
        string strResult = "";
        strResult = Convert.ToString(Operation.GetResult(ConvertToDouble(strNumberA), ConvertToDouble(strNumberB), strOperate));
        Console.WriteLine("结果是:" + strResult);
        Console.ReadLine();
    }
    catch(Exception ex)
    {
        Console.WriteLine("您的输入有错:" + ex.Message);
    }   
}

有了面向对象的思想了吗?面向对象有三大特性:封装,继承,多态,这里只用到了封装,继续改。

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

现在的问题是如何去实例化对象。好了,重点来了。”简单工厂模式”告诉你到底要实例化谁,将来会不会增加实例化的对象,我们应该考虑用单独的一个类来做这个创造实例的过程,这就是工厂。
简单运算工厂类:

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

现在不关你是控制台程序,Windows程序,Web程序,PDA或手机程序,都可以采用这段代码来实现计算机的功能,如果有一天我们需要更改加法运算,只需要更改OperationAdd。如果需要增加各种复杂运算,只要增加相应的运算子类然后修改运算类工厂,在switch中添加分支就可以了,如果需要修改界面,直接修改就可以不需要修改运算。

心得:编程是一门技术,更是一项艺术。我们不能只满足于运行结果正确。时常考虑让代码更加简练,更加容易维护,容易扩展和复用,这样才不叫“搬砖”,才能得到真正提高。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值