1、代码无错就是优?简单工厂模式

面试题:
请使用JAVA面向对象语言实现一个计算器控制台程序
我们来看下面一段代码:

/**
 * 请使用JAVA面向对象语言实现一个计算器控制台程序
 * Created by ZhuPengWei on 2018/1/24.
 */
public class OriginalCode {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入数字A");
            Integer A = sc.nextInt();
            System.out.println("请选择运算符号(+ - * /): ");
            String symbol = sc.next();
            System.out.println("请输入数字B");
            Integer B = sc.nextInt();
            switch (symbol) {
                case "+":
                    System.out.println("结果是:" + (A + B));
                    break;
                case "-":
                    System.out.println("结果是:" + (A - B));
                    break;
                case "*":
                    System.out.println("结果是:" + A * B);
                    break;
                case "/":
                    if (0 == B) {
                        System.out.println("除数不能为0");
                    } else {
                        System.out.println("结果是:" + A / B);
                    }
                    break;
                default:
                    System.out.println("您的输入有误");

            }
        }
    }
}

比如计算器这个程序,先要求输入两个数和运算符号,然后根据运算符号判断选择如何运算,得到结果,这本身没有错,但这样的思维却使得我们的程序只实现当前的需求,程序不容易维护,不容易扩展,更加不容易复用,从而达不到高质量代码的要求

1. 业务的封装

准确的来说,就是让业务与界面逻辑分开,让他们的耦合度下降。只有分离开
才可以打到容易维护或者扩展
Operatation运算类

/**
 * 运算类
 * Created by ZhuPengWei on 2018/1/24.
 */
public class Operation {

    /**
     * 获取结果
     *
     * @param numberA 数字A
     * @param numberB 数字B
     * @param operate 操作运算符
     * @return 结果
     */
    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 "/":
                if (0 == numberB) {
                    throw new RuntimeException("除数不能为0");
                } else {
                    result = numberA * numberB;
                }
                break;
            default:
                throw new RuntimeException("您的输入有误");

        }
        return result;

    }
}
/**
 * 客户端
 * Created by ZhuPengWei on 2018/1/24.
 */
public class Client {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入数字A");
            Double numberA = sc.nextDouble();
            System.out.println("请选择运算符号(+ - * /): ");
            String operate = sc.next();
            System.out.println("请输入数字B");
            Double numberB = sc.nextDouble();
            // 获取计算结果
            double result = Operation.getResult(numberA, numberB, operate);
            System.out.println("结果是:" + result);
        }
    }
}

这样的代码完全的把业务和界面分离了。但是这样的代码,能否做到很灵活的可修改和可扩展呢???

2. 使用多态和继承继续改进代码

新的需求:
现在如果我想增加一个开根(sqrt)运算,如何改?
是否只是该Opration类,在switch中加一个分支就行了?
问题是要加一个平方根运算,却需要让加减乘除运算都得来参与编译,如果一不小心,更改了原有代码的逻辑,这样看起来确实是很糟糕
打个比方,如果现在公司要求你为公司的薪资管理系统做维护,原来只有技术人员(月薪),市场销售人员(底薪+提成),经理(年薪+股份)
三种运算算法,现在要增加兼职工作人员(时薪)的算法,但按照上面一种的写法,公司就必须要把包含原三种算法的运算类给你,让你修改,
你如果心中小算盘一打,“TMD,公司给我的工资这么低,我真的是很郁闷,这下有机会了”,于是你除了增加兼职算法以外,在技术人员(月薪)
算法中写了一句

if(员工是xxxx){
    salary =salary* 1.1;
}

那就意味着,你的月薪每月都会增加10%(小心被抓),本来是让你增加一个功能,却使得原有的运行良好的功能代码产生了变化,这个风险太大了。

改进:首先是一个运算类,他有两个Number属性,主要用于计算器的前后数,然后有一个虚方法getResult(),用于得到结果,然后我把加减乘除都写成了
运算类的子类,继承它后,重写了getResult()方法,这样如果要修改任何一个算法,就不需要提供其他算法的代码了


/**
 * 运算类
 * Created by ZhuPengWei on 2018/1/24.
 */
public class Operation {

    private double numberA = 0d;
    private double numberB = 0d;

    public double getResult() {
        return 0d;
    }

    public double getNumberA() {
        return numberA;
    }

    public void setNumberA(double numberA) {
        this.numberA = numberA;
    }

    public double getNumberB() {
        return numberB;
    }

    public void setNumberB(double numberB) {
        this.numberB = numberB;
    }
}
/**
 * 加法运算类
 * Created by ZhuPengWei on 2018/1/24.
 */
public class OperationAdd extends Operation {
    @Override
    public double getResult() {
        double result = 0d;
        result = getNumberA() + getNumberB();
        return result;
    }
}
/**
 * 减肥运算类
 * Created by ZhuPengWei on 2018/1/24.
 */
public class OperationSub extends Operation {
    @Override
    public double getResult() {
        double result = 0d;
        result = getNumberA() - getNumberB();
        return result;
    }
}
/**
 * 乘法运算类
 * Created by ZhuPengWei on 2018/1/24.
 */
public class OperationMul extends Operation {
    @Override
    public double getResult() {
        double result = 0d;
        result = getNumberA() * getNumberB();
        return result;
    }
}
/**
 * 除法运算类
 * Created by ZhuPengWei on 2018/1/24.
 */
public class OperationDiv extends Operation {
    @Override
    public double getResult() {
        double result = 0d;
        result = getNumberA() / getNumberB();
        return result;
    }
}

3. 简单工厂模式

/**
 * 简单工厂模式
 * Created by ZhuPengWei on 2018/1/25.
 */
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;
    }
}

客户端代码

/**
 * 客户端
 * Created by ZhuPengWei on 2018/1/25.
 */
public class Client {
    public static void main(String[] args) {
        Operation operate;
        operate = OperationFactory.createOperate("+");
        operate.setNumberA(12);
        operate.setNumberB(13);
        System.out.println(operate.getResult());
    }
}

如果我们需要增加各种复杂的运算,比如说平方根、立方根、自然对数、正弦余弦等,只需要增加响应的运算子类并且修改运算类工厂,在switch中增加分支

猜你喜欢

转载自blog.csdn.net/qq_36144258/article/details/79161047