设计模式--简单工厂模式

简单工厂模式

          相信很多人都听过设计模式吧,但是也只是局限于听说。很多人认为设计模式并没啥用啊(当然也包括我),我自己写的代码也可以完成需求,为啥还要设计模式呢?
          在你学习之后会感叹代码还可以这么写,同时也能够更加熟练的运用面向对象的思想。本系列的文章来源于《大话设计模式》,感兴趣的朋友们可以找来阅读一番,很不错的一本书。
          直接开始正文吧,我们要实现两个数的运算,用户输入两个数字和一个操作符后,返回运算结果。

          相信各位能够很容易实现该代码如下:

public class Program {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入数字A:");
        String strNumA = scanner.nextLine();
        System.out.print("请输入数字B:");
        String strNumB = scanner.nextLine();
        System.out.println("请输入运算符:");
        String strOper = scanner.nextLine();
        if("+".equals(strOper)){
            System.out.println(Double.parseDouble(strNumA) + Double.parseDouble(strNumB));
        }
        if("-".equals(strOper)){
            System.out.println(Double.parseDouble(strNumA) - Double.parseDouble(strNumB));
        }
        if("*".equals(strOper)){
            System.out.println(Double.parseDouble(strNumA) * Double.parseDouble(strNumB));
        }
        if("/".equals(strOper)){
            System.out.println(Double.parseDouble(strNumA) / Double.parseDouble(strNumB));
        }
    }
}

          但是我们可以发现,该段代码依然有很多问题,如:用户输入非法值时,我们没有进行异常处理;其次,当进行除法运算时,除数为0的话,我们也并没有进行判断;接着不断我输入哪个运算符,四个if语句都执行了,虽然说计算机运算速度,但是我们写出精炼的代码,能够让别人感觉到你的代码水平较高。
          改进后的代码如下:

public class Program {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入数字A:");
        String strNumA = scanner.nextLine();
        System.out.print("请输入数字B:");
        String strNumB = scanner.nextLine();
        System.out.print("请输入运算符:");
        String strOper = scanner.nextLine();
        try {
           double result = 0;
            if ("+".equals(strOper)) {
                result = Double.parseDouble(strNumA) + Double.parseDouble(strNumB);
            }
            else if ("-".equals(strOper)) {
                result = Double.parseDouble(strNumA) - Double.parseDouble(strNumB);
            }
            else if ("*".equals(strOper)) {
                result = Double.parseDouble(strNumA) * Double.parseDouble(strNumB);
            }
            else if ("/".equals(strOper)) {
                if(Double.parseDouble(strNumB)!=0)
                    result = Double.parseDouble(strNumA) / Double.parseDouble(strNumB);
                else
                    System.out.println("除数不能为0!");
            }else{
                System.out.println("请输入指定运算符!");
                return;
            }
            System.out.println("运算结果:"+result);
        }catch (NumberFormatException e){
            System.out.println("请输入合法值!");
        }
    }
}

          观察上面的代码后,是不是觉得你写的代码已经很完善了,但是这是一个完全面向过程的程序吧。面向对象的三大特征封装、继承、多态好像并没有使用吧。该段程序的耦合度很高,高质量的程序应该是耦合度很低的,所以我们应该将业务逻辑与业务逻辑无关的分离,降低彼此之间的耦合度。
          实现代码如下:

public class Operation {

    public static double getResult(double numA,double numB,String oper) throws Exception {
        double result = 0;
        switch (oper){
            case "+":
                result = numA + numB;
                break;
            case "-":
                result = numA - numB;
                break;
            case "*":
                result = numA * numB;
                break;
            case "/":
                if(numB != 0) {
                    result = numA / numB;
                }else{
                    throw new Exception("除数不能为0!");
                }
                break;
            default:
                throw new Exception("请输入指定运算符!");
        }
        return result;
    }
}

public class Program {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入数字A:");
        String strNumA = scanner.nextLine();
        System.out.print("请输入数字B:");
        String strNumB = scanner.nextLine();
        System.out.print("请输入运算符:");
        String strOper = scanner.nextLine();
        try {
            double result = Operation.getResult(Double.parseDouble(strNumA),Double.parseDouble(strNumB),strOper);
            System.out.println("运算结果:"+result);
        }catch (NumberFormatException e){
            System.out.println("请输入合法值!");
        }
        catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}

          如此一来,我们便将调用者与业务逻辑之间进行了解耦和。
          但是,如果我们要增加其他运算呢?如求平方根,求次方的话会怎么做?相信大家的想法是在Operation类中增加case语句不就好了吗?但是这样做的话,我们得更改原程序的代码。通常来说,是很忌讳直接去修改原程序的代码。这时,我们就可以运用面向对象的其他特征了。


public abstract class Operation {

    public abstract double getResult(double numA,double numB) throws Exception;

}

class OperAdd extends Operation{

    @Override
    public double getResult(double numA, double numB) {
        return numA + numB;
    }
}

class OperSub extends Operation{

    @Override
    public double getResult(double numA, double numB) {
        return numA - numB;
    }
}

class OperMul extends Operation{

    @Override
    public double getResult(double numA, double numB) {
        return numA * numB;
    }
}

class OperDiv extends Operation{

    @Override
    public double getResult(double numA, double numB) throws Exception {
        if(numB == 0)
            throw new Exception("除数不能为0!");
        return numA / numB;
    }
}


          我们通过判断运算符的类型,继承父类生成合适的子类对象,利用多态即可。这样的话,当需要其他功能时,我们只需要继续去继承父类即可。而我们生成合适子类的过程中便用到了简单工厂模式。
          简单工厂模式示例代码如下:

public class OperFactory {
    public Operation createOper(String oper) throws Exception {
        Operation operation = null;
        switch (oper){
            case "+":
                operation = new OperAdd();
                break;
            case "-":
                operation = new OperSub();
                break;
            case "*":
                operation = new OperMul();
                break;
            case "/":
                operation = new OperDiv();
                break;
            default:
                throw new Exception("请输入指定运算符");
        }
        return operation;
    }
}

          当我们进行运算时,让工厂产生合适的子类对象,这样我们就可以进行运算了。

public class Program {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入数字A:");
        String strNumA = scanner.nextLine();
        System.out.print("请输入数字B:");
        String strNumB = scanner.nextLine();
        System.out.print("请输入运算符:");
        String strOper = scanner.nextLine();


        try {
            //生成工厂对象
            OperFactory factory = new OperFactory();
            //生成合适的子类对象
            Operation oper = factory.createOper(strOper);
            //利用多态进行计算
            double result = oper.getResult(Double.parseDouble(strNumA),Double.parseDouble(strNumB));
            System.out.println("运算结果:"+result);
        }catch (NumberFormatException e){
            System.out.println("请输入合法数字!");
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

          这个OperFactory像不像一个工厂呢?如饮料厂生产饮料,根据用户的需求去生产合适的饮料。
          你可能还挺过静态工厂模式,那么什么时静态工厂呢?很简单,不过是将生产子类的方法由对象方法提升至类方法,这样我们就可以不用生成工厂对象,直接通过类去调用该方法即可。
          学习了简单工厂模式后,我们总结一下什么时候时候该设计模式,首先对需求进行分习,如上可以分离出一个抽象类:运算类。然后该类的方法在不同的条件下有不同的执行过程。那么,此时我们便可以使用简单工厂模式。
          个人博客:https://wshuaigit.github.io

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值