2019年05月25日(星期六)  农历:己亥年四月廿一
  • 首页
  • JAVA
  • 一个对面向对象的理解的例子

作者:三年。分类: JAVA

    菜鸟一枚,求亲喷~!

    今天在网上无意间看到一道面试题,感觉挺有意思的,题目是这样:"请用任意一种面向对象语言实现一个计算机控制台程序,要求输入两个数和运算符号,输出结果”。

     第一遍的时候还在想,居然还有这么简单的面试题?花了几分钟敲了一下这个程序,代码如下(为了方便,代码本身不规范,很多情况并未考虑):


public class Calculator {

    public static void main(String[] args) {
        System.out.println("请输入第一个数字:");
        Scanner input1 = new Scanner(System.in);
        int numberOne = input1.nextInt();
        System.out.println("请输入运算符:");
        Scanner input2 = new Scanner(System.in);
        String operation = input2.nextLine();
        System.out.println("请输入第二个数字:");
        Scanner input3 = new Scanner(System.in);
        int numberTwo = input3.nextInt();
        int result = 0;
        switch (operation) {
            case "+":
                result = numberOne + numberTwo;
                break;
            case "-":
                result = numberOne - numberTwo;
                break;
            case "*":
                result = numberOne * numberTwo;
                break;
            case "/":
                if (numberTwo != 0) {
                    result = numberOne / numberTwo;
                } else {
                    result = -9999999; //表示出问题
                }
                break;

            default:

                result = -8888888; //表示输入运算符号错误

        }
        System.out.println("结果是: " + result);
    }
}

     然而当我再回看题目的时候,发现实际上也没有那么简单。题目上表明了“面向对象语言”,虽然java是面向对象的语 言,然而很显然上面的解法只是单纯的面向过程的解法。当我们看到一个问题的时候,总是很容易用很简单的逻辑去解决问题(可能菜鸟都会这样,比如少 爷...),虽然这样的答案没有错,然而却没有领略到面向对象的精髓。

       那么,面向对象的精髓又是什么呢?

       当我们在学Java的时候,老师对会说,Java你们一定要深入的去理解[封装]、[继承]和[多态]。

       这三个特性的好处有很多很多(之后会另开文分别分析),总结来说:面向对象的编程方法就是利用这三个特性让程序的耦合度降低,使得程序可以更容易维护,复用和扩展。

       比如说上面的一段代码,如果某一天,我不想在控制台用了,想换到web,移动端等等,那么,上面的代码,我们可以去复用吗?

       很多人可能会说,可以啊,功能那里直接复制粘贴就好了嘛!

       但是想想,就这么简单的一段倒是没关系,如果你在一千个地方,一万个地方都写了这段代码呢?(估计正常人都会疯了...)

       所以,在编程的时候,我们应该尽量去避免重复代码。

       这个时候,我们可以考虑一下,是不是可以把里面的业务部分和界面分离开呢?

       此时,便可以考虑采用封装,把功能从界面中分离开来,具体代码如下:

     public class UI {
    public static void main(String[] args) {
        System.out.println("请输入第一个数字:");
        Scanner input1 = new Scanner(System.in);
        int numberOne = input1.nextInt();
        System.out.println("请输入运算符:");
        Scanner input2 = new Scanner(System.in);
        String operation = input2.nextLine();
        System.out.println("请输入第二个数字:");
        Scanner input3 = new Scanner(System.in);
        int numberTwo = input3.nextInt();
        int result = 0;
        result = Calculator.getResult(numberOne, operation, numberTwo);
        System.out.println("结果是: " + result);
    }
}

public class Calculator {

    public static int getResult(int numberOne,String operation,int numberTwo) {
        int result = 0;
        switch (operation) {
            case "+":
                result = numberOne + numberTwo;
                break;
            case "-":
                result = numberOne - numberTwo;
                break;
            case "*":
                result = numberOne * numberTwo;
                break;
            case "/":
                if (numberTwo != 0) {
                    result = numberOne / numberTwo;
                } else {
                    result = -9999999; //表示出问题
                }
                break;
        }
        return result;
    }
}




       这样的话,不管是用到什么地方,至少运算这一部分的代码相对之前那个,会更好用一些。

       当然,这也只是用到了三个特性中的一个。比如说,有一天,我突然还想用一些其他的运算方式,比如说乘方,开方,求余等等,又该怎么做呢? 当然,我们可以选择直接修改运算类中switch语句,直接加上一个新功能。然而,这样真的合理吗?比如说,switch里面已经有成百上千中运算方式 了,而且运算方式也比较复杂,你为了加多一种,就要重新编译一次所有的运算方法,而且,还有可能不小心修改了之前实现好的东西(比如说银行存钱的加法变成 了减法,呵呵呵......),这样就太不划算了。

       所以,当我们在写程序的时候,应该尽可能的把功能独立开来,修改其中一个或者新增功能,对其他的不造成影响。

       此时,我们可以考虑一下继承,具体代码如下:

public class Calculator {
    
    public int getResult(int numberOne,int numberTwo) {
        int result = 0;
        return result;
    }
}

public class Add extends Calculator {

    @Override
    public int getResult(int numberOne,int numberTwo) {
        int result = 0;
        result = numberOne + numberTwo;
        return result;
    }
}

public class Sub extends Calculator{
    @Override
    public int getResult(int numberOne,int numberTwo) {
        int result = 0;
        result = numberOne - numberTwo;
        return result;
    }
}



     这个时候,不管我们是要修改功能,还是新添加功能,都不会再去影响原有的功能。当然,此时还要考虑一个问题就是,怎么知道调用的是什么功能呢?

       这个时候可以利用Java多态特性,同时利用简单工程模式来简化理解。简单工厂类代码如下:

public class SimpleFactory {
    public static Calculator createCalculator(String operation){
        Calculator calculator = null;
        switch(operation){
            case "+":
                calculator = new Add();
               break;
            case "-":
                calculator = new Sub();
                break;
        }
        return calculator;
    }
}



   客户端代码:

      

  public class UI {
    public static void main(String[] args) {
        System.out.println("请输入第一个数字:");
        Scanner input1 = new Scanner(System.in);
        int numberOne = input1.nextInt();
        System.out.println("请输入运算符:");
        Scanner input2 = new Scanner(System.in);
        String operation = input2.nextLine();
        System.out.println("请输入第二个数字:");
        Scanner input3 = new Scanner(System.in);
        int numberTwo = input3.nextInt();
        int result = 0;
        Calculator calculator = null;
        calculator = SimpleFactory.createCalculator(operation);
        result = calculator.getResult(numberOne,numberTwo);
        System.out.println("结果是: " + result);
    }

}


        总结:面向对象的编程方法就是让程序的耦合度降低,使得程序可以更容易维护,复用和扩展。(copy了上文)

               

 

        PS:感觉可能有些东西还没有说清楚,也只是回想了一下当年老师说过的栗子,只能说本文只是当做一个入门吧,以后有什么新的想法再继续修改。各位大神有其他高见的希望指出



温馨提示如有转载或引用以上内容之必要,敬请将本文链接作为出处标注,谢谢合作!

已有 0/1933 人参与

发表评论:



手Q扫描加入Java初学者群