编程语言
首页 > 编程语言> > 《大话设计模式》-简单工厂模式(java)

《大话设计模式》-简单工厂模式(java)

作者:互联网

简单工厂模式

1.面试受挫

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

1.1小菜的代码

import java.util.Scanner;

/**
 * @author qyq
 * @create 2021-03-12-13:37
 * 请用C++、Java、C#或VB.NET任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果。
 */
public class Program {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入数字A:");
        String A = scanner.nextLine();
        System.out.println("请选择运算符号(+,-,*,/):");
        String B = scanner.nextLine();
        System.out.println("请输入数字B:");
        String C = scanner.nextLine();
        String D = "";

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

1.2初学者代码毛病

在这里插入图片描述

1.3小菜更改代码规范

public static void main(String[] args) {
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入数字A:");
            String strNumberA = scanner.nextLine();
            System.out.println("请选择运算符号(+,-,*,/):");
            String strOperator = scanner.nextLine();
            System.out.println("请输入数字B:");
            String strNumberB = scanner.nextLine();
            String strResult = "";

            switch (strOperator) {
                case "+":
                    strResult = (Double.parseDouble(strNumberA) + Double.parseDouble(strNumberB)) + "";
                    break;
                case "-":
                    strResult = (Double.parseDouble(strNumberA) - Double.parseDouble(strNumberB)) + "";
                    break;
                case "*":
                    strResult = (Double.parseDouble(strNumberA) * Double.parseDouble(strNumberB)) + "";
                    break;
                case "/":
                    if (!"0".equals(strNumberB)) {
                        strResult = (Double.parseDouble(strNumberA) / Double.parseDouble(strNumberB)) + "";
                    } else {
                        strResult = "除数不能为0";
                    }
                    break;
            }
            System.out.println("结果是:" + strResult);
        }catch (Exception e) {
            System.out.println("你输入的有错误:" + e.getMessage());
        }
    }

1.4面向对象编程

“所有编程初学者都会有这样的问题,就是碰到问题就直觉地用计算机能够理解的逻辑来描述和表达待解决的问题及具体的求解过程。这其实是用计算机的方式去思考,比如计算器这个程序,先要求输入两个数和运算符号,然后根据运算符号判断如何运算,得到结果,这本身没有错,但这样的思维却使得我们的程序只为满足实现当前的需求,程序不容易维护,不容易扩展,更不容易复用。从而达不到高质量代码的要求。”

1.5活字印刷,面向对象

在这里插入图片描述
引出的思考:

  1. 要改,只需更改要改之字,此为可维护
  2. 这些字并非用完这次就无用,完全可以在后来的印刷中重复使用,此乃可复用
  3. 此诗若要加字,只需刻字加入即可,这是可扩展
  4. 字的排列其实可能是竖排也可能是横排,此时只需将活字移动就可做到满足排列需求,此是灵活性好
    可维护、可复用、可扩展、灵活性好这四点,不仅仅是面向对象编程的一个起始点更是我们对待每一个程序应用一个较好的编程思想!
    程序的编程思想:自顶向下,精益求精!

1.6面向对象的好处

通过封装、继承、多态把程序的耦合度降低。
通过设计模式使得程序更加灵活,容易修改,并且易于复用。

1.7复制和复用

在这里插入图片描述

1.8业务的封装

准确地说,就是让业务逻辑与界面逻辑分开,让它们之间的耦合度下降。只有分离开,才可以达到容易维护或扩展。

Operation运算类

public class Operation {
    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 "/":
                result = numberA / numberB;
                break;
        }
        return result;
    }
}

客户端:

public static void main(String[] args) {
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入数字A:");
            String strNumberA = scanner.nextLine();
            System.out.println("请选择运算符号(+,-,*,/):");
            String strOperator = scanner.nextLine();
            System.out.println("请输入数字B:");
            String strNumberB = scanner.nextLine();
            String strResult = "";


            strResult = Operation.GetResult(Double.parseDouble(strNumberA), Double.parseDouble(strNumberB), strOperator) + "";

            System.out.println("结果是:" + strResult);
        }catch (Exception e) {
            System.out.println("你输入的有错误:" + e.getMessage());
        }
    }

如此的代码编程,不单是Windows程序,Web版程序需要运算也可以用它,PDA、手机等需要移动系统的软件需要运算也可以用它。但仅此而已,还谈不上完全面向对象,此处仅仅只用了面向对象三大特性中的其中一个(封装),还有两个没用(继承和多态)呢!

1.9 紧耦合 vs 松耦合

大鸟:考虑一下,昨天的代码是否已做到很灵活的可修改和扩展呢?
小菜:我已经把业务和界面分离了呀,这不是很灵活吗?
大鸟:现在如果我希望增加一个开根(sqrt)运算,你会如何改?
小菜:那只需要改Operation类就行了,在switch中加一个分支就行了。
大鸟:问题是你要加一个平方根运算,却需要让加减乘除的运算都得来参与编译,如果你一不小心把加法运算改成了减法,这岂不是大大的糟糕。打个比方,如果现在公司要求你为公司的薪资管理系统做维护,原来只有技术人员(月薪),市场销售人员(底薪+提成),经理(年薪+股份)三种运算算法,现在要增加兼职工作人员(时薪)的算法,但按照上述的程序写法,公司就必须要把包含原三种算法的运算类给你,让你修改,你如果心中小算盘一打,‘TMD!公司给我的工资这么低,这下有机会了’,于是你除了增加了兼职算法以外,在技术人员(月薪)算法中写了一句。

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

如此就意味着,你的月薪每月都会增加10%(小心被抓去坐牢),本来是让你加一个功能,却使得原有运行良好的功能代码产生了变化,这个风险太大了!”
小菜重写:Operation运算类

/**运算类
 */
public abstract class Operation {
    private double _numberA = 0;
    private double _numberB = 0;
    public double get_numberA() {
        return _numberA;
    }
    public void set_numberA (double _numberA) {
        this._numberA = _numberA;
    }
    public double get_numberB() {
        return _numberB;
    }
    public void set_numberB(double _numberB) {
        this._numberB = _numberB;
    }

    public abstract double getResult();
  }

加减乘除类

/*
    加法类,继承运算类
 */
class OperationAdd extends Operation {
    @Override
    public double getResult() {
        double result = 0;
        result = get_numberA() + get_numberB();
        return result;
    }
}

/*
    减法类,继承运算类
 */
class OperationSub extends Operation {
    @Override
    public double getResult() {
        double result = 0;
        return get_numberA() - get_numberB() ;
    }
}

/*
    乘法类,继承运算类
 */
class OperationMul extends Operation {
    @Override
    public double getResult() {
        double result = 0;
        result = get_numberA() * get_numberB();
        return result;
    }
}

/*
    除法类,继承运算类
 */
class OperationDiv extends Operation {
    @Override
    public double getResult() {
        double result = 0;
        if (get_numberB() == 0) {
            try {
                throw new Exception("除数不能为0");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        result = get_numberA() / get_numberB() ;
        return result;
    }
}

在这里插入图片描述

1.10 简单工厂模式

在这里插入图片描述

/**
 * @author qyq
 * @create 2021-03-12-15:00
 * 简单运算工厂类
 */
public class OperationFacotry {
    public static Operation createOperate(String operate) {
        Operation operation = null;
        //注意两个单词的拼写不一样哦
        switch (operate) {
            case "+":
                operation = new OperationAdd();
                break;
            case "-":
                operation = new OperationSub();
                break;
            case "*":
                operation = new OperationMul();
                break;
            case "/":
                operation = new OperationDiv();
                break;
        }
        return operation;
    }
}

客户端代码

public static void main(String[] args) {
        Operation operation;
        operation = OperationFacotry.createOperate("-");
        operation.set_numberA(1);
        operation.set_numberB(2);
        double result = operation.getResult();
        System.out.println("结果是:"+result);
  }

如此一来,那么我们需要增加各种复杂运算,比如平方根,立方根,自然对数,正弦余弦等,只需增加相应的运算子类就可以了。
在这里插入图片描述
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。 – 百度百科解释

感谢阅读

标签:java,double,大话,parseDouble,System,result,numberB,设计模式,public
来源: https://blog.csdn.net/One_Piece111/article/details/114693969