【设计模式】《大话设计模式》——简单工厂模式

计算器代码

请用C++、Java、C#、或VB.NET任意的一种面向对象语言实现一个计算器控制台应用程序,要求输入两个数和运算符号,得到结果。

1、最简(yú)单(chǔn)的实现

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入数字A:");
        String A = scan.nextLine();
        System.out.println("请输入运算符号(+、-、*、/):");
        String B = scan.nextLine();
        System.out.println("请输入数字B:");
        String C = scan.nextLine();
        String D = "";

        if (B.equals("+")) {
            D = String.valueOf(Double.parseDouble(A) + Double.parseDouble(C));
        }
        if (B.equals("-")) {
            D = String.valueOf(Double.parseDouble(A) - Double.parseDouble(C));
        }
        if (B.equals("*")) {
            D = String.valueOf(Double.parseDouble(A) * Double.parseDouble(C));
        }
        if (B.equals("/")) {
            D = String.valueOf(Double.parseDouble(A) / Double.parseDouble(C));
        }
        System.out.println("结果是:" + D);
    }
}

点评:

  • 1 命名不规范
  • 2 判断分支这样写意味着每个条件都要判断,计算机做了三次无用功
  • 3 未考虑程序异常情况
    • 3.1 输入非法数字(java.lang.NumberFormatException)
    • 3.2 非法运算符(跳过所有判断分支,输出空字符串)
    • 3.3 除数为0(java.lang.ArithmeticException: / by zero)

思考

  • 改进程序,解决上述隐患与不规范

2、代码规范化

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        try {
            Scanner scan = new Scanner(System.in);
            System.out.println("请输入数字A:");
            String strNumberA = scan.nextLine();
            System.out.println("请输入运算符号(+、-、*、/):");
            String strOperate = scan.nextLine();
            System.out.println("请输入数字B:");
            String strNumberB = scan.nextLine();
            String strResult = "";
            switch (strOperate) {
                case "+":
                    strResult = String.valueOf(Double.parseDouble(strNumberA) + Double.parseDouble(strNumberB));
                    break;
                case "-":
                    strResult = String.valueOf(Double.parseDouble(strNumberA) - Double.parseDouble(strNumberB));
                    break;
                case "*":
                    strResult = String.valueOf(Double.parseDouble(strNumberA) * Double.parseDouble(strNumberB));
                    break;
                case "/":
                    if (Double.parseDouble(strNumberB) != 0) {
                        strResult = String.valueOf(Double.parseDouble(strNumberA) / Double.parseDouble(strNumberB));
                    } else {
                        strResult = "除数不能为0!";
                    }
                    break;
                default:
                    strResult = "非法运算符!";
            }
            System.out.println("结果是:" + strResult);
        } catch (Exception e) {
            System.out.println("您的输入有误:" + e.getMessage());
        }
    }
}

点评

  • 1 没有体现面向对象
  • 2 可以考虑使用简单工厂模式

思考

  • 如何使程序变得可维护可复用可拓展灵活性好
    • 通过封装继承多态把程序的耦合度降低
    • 设计模式使得程序更加的灵活,容易修改,并且易于复用

3、面向对象之封装

Operation运算类


public class Operation {

    public static String getResult(double numberA, double numberB, String operate) {
        String result = "";
        switch (operate) {
            case "+":
                result = String.valueOf(numberA + numberB);
                break;
            case "-":
                result = String.valueOf(numberA - numberB);
                break;
            case "*":
                result = String.valueOf(numberA * numberB);
                break;
            case "/":
                if (numberB != 0) {
                    result = String.valueOf(numberA / numberB);
                } else {
                    result = "除数不能为0!";
                }
                break;
            default:
                result = "非法运算符!";
        }
        return result;
    }

}

客户端代码

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        try {
            Scanner scan = new Scanner(System.in);
            System.out.println("请输入数字A:");
            String strNumberA = scan.nextLine();
            System.out.println("请输入运算符号(+、-、*、/):");
            String strOperate = scan.nextLine();
            System.out.println("请输入数字B:");
            String strNumberB = scan.nextLine();
            String strResult = Operation.getResult(
                    Double.parseDouble(strNumberA),
                    Double.parseDouble(strNumberB),
                    strOperate);
            System.out.println("结果是:" + strResult);
        } catch (Exception e) {
            System.out.println("您的输入有误:" + e.getMessage());
        }
    }
}

点评

  • 完全把业务和界面分离了
  • 运算类(Operation) 可复用
  • 只用到了面向对象的封装

思考

  • 如何将面向对象的另外两大特征(继承多态)应用在程序中?

4、面向对象之继承多态+简单工厂模式

Operation运算类

public abstract class Operation {

    protected double numberA;
    protected double numberB;

    public abstract String getResult();
}

加减乘除类

public class OperationAdd extends Operation {

    @Override
    public String getResult() {
        return String.valueOf(numberA + numberB);
    }
}
public class OperationSub extends Operation {
    @Override
    public String getResult() {
        return String.valueOf(numberA - numberB);
    }
}
public class OperationMul extends Operation {
    @Override
    public String getResult() {
        return String.valueOf(numberA * numberB);
    }
}
public class OperationDiv extends Operation {
    @Override
    public String getResult() {
        if (numberB == 0) {
            return "除数不能为0";
        }
        return String.valueOf(numberA / numberB);
    }
}

运算工厂类


public class OperationFactory {
    public static Operation create(String operate) throws Exception {
        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;
            default:
                throw new Exception("非法运算符");
        }
        return oper;
    }
}

客户端核心代码

Operation oper = OperationFactory.create(strOperate);
oper.numberA = Double.parseDouble(strNumberA);
oper.numberB = Double.parseDouble(strNumberB);
System.out.println("结果是:" + oper.getResult());

点评

  • 运算父类及子类、运算工厂类封装完成,可复用性高
  • 如果只修改具体的某一运算(如:乘法运算),只需要修改该类就可以了。减轻了耦合度。同时也减轻了编译负担(对比1、2、3的代码)。可维护性好。
  • 如果要增加运算。则只需要增加新的运算类,以及在运算工厂类中增加该运算的判断。逻辑清晰明了。可拓展性好,灵活性好。
  • 如果修改界面,运算相关的类一个也不用改。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值