zoukankan      html  css  js  c++  java
  • 大话设计模式之简单工厂模式

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

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

    需求

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

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

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

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

  • 相关阅读:
    Android微信九宫格图片展示控件
    ImageView设置rounded corner
    Android TitleBar推荐
    《Windows核心编程》目录索引
    《Windows内核分析》专题-索引目录
    wchar,char,string,wstring互转
    键盘过滤
    串口过滤
    Vmware中Linux 虚拟机与Windows物理机建立共享文件夹
    遍历某一进程模块
  • 原文地址:https://www.cnblogs.com/tyhA-nobody/p/13173409.html
Copyright © 2011-2022 走看看