大话设计模式之简单工厂模式

大话设计模式——简单工厂模式

--参考自《大话设计模式》

需求

现在有一个需求,实现一个简单的计算器

对于一般的初学者来说可能会这么实现:

public class calculate {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        System.out.println("请输入数字A:");
        String numberA = cin.next();

        System.out.println("请输入运算符号(+,-,*,/):");
        char op = cin.next().charAt(0);
        System.out.println("请输入数字B:");
        String numberB = cin.next();
        String rst = null;
        if(op == '+'){
            rst = String.valueOf(Integer.parseInt(numberA)+Integer.parseInt(numberB));
        }
        if(op == '-'){
            rst = String.valueOf(Integer.parseInt(numberA)-Integer.parseInt(numberB));
        }
        if(op == '*'){
            rst = String.valueOf(Integer.parseInt(numberA)*Integer.parseInt(numberB));
        }
        if(op == '/'){
            rst = String.valueOf(Integer.parseInt(numberA)/Integer.parseInt(numberB));
        }
        System.out.println("结果是: " + rst);
    }
}

修改后的版本:

public class calculate2 {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);

        try {
            System.out.println("请输入数字A:");
            String numberA = cin.next();
            System.out.println("请输入运算符号(+,-,*,/):");
            char op = cin.next().charAt(0);
            System.out.println("请输入数字B:");
            String numberB = cin.next();
            String rst = null;
            switch (op){
                case '+':rst = String.valueOf(Integer.parseInt(numberA)+Integer.parseInt(numberB));break;
                case '-':rst = String.valueOf(Integer.parseInt(numberA)-Integer.parseInt(numberB));break;
                case '*':rst = String.valueOf(Integer.parseInt(numberA)*Integer.parseInt(numberB));break;
                case '/':
                    if(!numberB.equals("0")){
                        rst = String.valueOf(Integer.parseInt(numberA)/Integer.parseInt(numberB));
                    }else{
                        rst = "除数不能为0!";
                    }
                    break;
            }
            System.out.println("结果是: " + rst);
        }catch (Exception e){
            System.out.println("您的输入有错:"+e.getMessage());
        }
    }
}

已经改的不错了,但是这种代码相对来说,可维护性和可扩展性低,如果现在需要重新写一个计算器,那么想一想我们的代码能不能复用呢?

那....Crtl+C和Crtl+V大法呀,多香呀。

有人说初级程序员的工作就是Crtl+C和Crtl+V,其实这是非常不好的编码习惯,想想当你的项目中,重复代码很多的时候,这就是一场灾难,有一个需求发生变化,那么你想想你得修改多少代码?

如果我们能将业务逻辑和客户端代码分开,让他们的耦合度下降,这样才能达到容易维护和扩展的目的。

我们将代码进行修改:

Operation类:

public class Operation {
    public static double getResult(double numberA,double numberB,String operate){
        double rst = 0.0;
        switch (operate.charAt(0)){
            case '+':
                rst = numberA + numberB;
                break;
            case '-':
                rst = numberA - numberB;
                break;
            case '*':
                rst = numberA * numberB;
                break;
            case '/':
                rst = numberA / numberB;
                break;
        }
        return rst;
    }
}

客户端逻辑代码:

public class testOperation {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        try{
            System.out.println("请输入数字A:");
            String numberA = cin.next();
            System.out.println("请输入运算符号(+,-,*,/):");
            String op = null;
            op = cin.next();
            System.out.println("请输入数字B:");
            String numberB = cin.next();
            System.out.println("结果是: "+ Operation.getResult(Double.parseDouble(numberA),Double.parseDouble(numberB),op));
        }catch (Exception e){
            System.out.println("您的输入有误:"+e.getMessage());
        }
    }
}

将业务逻辑和界面逻辑分离开,感觉维护性高多了,卧槽,牛逼呀。


问题又来了,如果现在要增加一个sqrt运算的需求怎么办,如何改?

只要修改Operation类,然后再switch里加一个分支就行了。

就增加了一个功能,就要让其他加减乘除所有的功能都参与运算,如果不小心改到加法运算里了怎么办?如果这是一个公司的计算工资的业务代码,如果参与维护的那个员工有私心,在完成sqrt运算的时候偷偷改了别的代码,改变了自己工资的计算方式,那岂不是风险太大了?

如果我们引入继承和多态,修改一个功能的时候不影响其他功能,这样风险就小很多。

operactionClass计算类:

public abstract  class operationClass {
    private double number_a = 0;
    private double number_b = 0;
    public  abstract double getResult();
    public operationClass() {
    }

    public double getNumber_a() {
        return number_a;
    }

    public void setNumber_a(double number_a) {
        this.number_a = number_a;
    }

    public double getNumber_b() {
        return number_b;
    }

    public void setNumber_b(double number_b) {
        this.number_b = number_b;
    }
}

加减乘除类都继承自运算类:

public class operationAdd extends operationClass {
    @Override
    public double getResult() {
        return getNumber_a() + getNumber_b();
    }
}

public class operationSub extends operationClass {
    @Override
    public double getResult() {
        return getNumber_a() + getNumber_b();
    }
}
public class operationMul extends operationClass{
    @Override
    public double getResult() {
        return getNumber_a() + getNumber_b();
    }
}
public class operationDiv  extends  operationClass{
    @Override
    public double getResult() throws Exception {
        if(getNumber_b() == 0){
            throw new Exception("被除数不能为0!");
        }
        return getNumber_a() + getNumber_b();
    }
}

实现了一部分,但是问题来了,我们如果让计算机知道我希望用哪一个算法呢?

简单工厂类##

现在就是到底要实例化谁?将来不会增加实例化的对象,比如增加sqrt功能,这是很容易变化的地方,应该用一个单独的类来做创造实例化的过程,这就是工厂。

简单工厂运算类:

public class operationFactory {
    public static operationClass createOperate(String op){
        operationClass operation = null;
        switch (op.charAt(0)){
            case '+':
                operation = new operationAdd();
                break;
            case '-':
                operation = new operationSub();
                break;
            case '*':
                operation = new operationMul();
                break;
            case '/':
                operation = new operationDiv();
                break;
        }
        return operation;
    }
}

只需要提供符号,就能生产出合适的实例化对象,通过多态,返回父类的方式实现了计算机的结果。

客户端代码实现 测试:

public class test {
    @Test
    public void testFactory() throws Exception {
        operationClass oper;
        oper = operationFactory.createOperate("+");
        oper.setNumber_a(11);
        oper.setNumber_b(22);
        System.out.println(oper.getResult());
    }
}

通过工厂模式,如果我们要增加复杂的运算,比如开根号,平方运算,只要增加相应的子类并且改造工厂的分支就可以了。这样就实现了业务逻辑和界面逻辑分离,功能模块之间的耦合也降低了。

原文地址:https://www.cnblogs.com/tyhA-nobody/p/13173409.html