一个对面向对象的理解的例子

一个对面向对象的理解的例子_第1张图片

 

     少爷菜鸟一枚,求轻喷。

     

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

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

     

 1 public class Calculator {
 2 
 3     public static void main(String[] args) {
 4         System.out.println("请输入第一个数字:");
 5         Scanner input1 = new Scanner(System.in);
 6         int numberOne = input1.nextInt();
 7         System.out.println("请输入运算符:");
 8         Scanner input2 = new Scanner(System.in);
 9         String operation = input2.nextLine();
10         System.out.println("请输入第二个数字:");
11         Scanner input3 = new Scanner(System.in);
12         int numberTwo = input3.nextInt();
13         int result = 0;
14         switch (operation) {
15             case "+":
16                 result = numberOne + numberTwo;
17                 break;
18             case "-":
19                 result = numberOne - numberTwo;
20                 break;
21             case "*":
22                 result = numberOne * numberTwo;
23                 break;
24             case "/":
25                 if (numberTwo != 0) {
26                     result = numberOne / numberTwo;
27                 } else {
28                     result = -9999999; //表示出问题
29                 }
30                 break;
31         }
32         System.out.println("结果是: " + result);
33     }
34 }

        

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

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

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

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

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

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

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

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

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

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

       

 1 public class UI {
 2     public static void main(String[] args) {
 3         System.out.println("请输入第一个数字:");
 4         Scanner input1 = new Scanner(System.in);
 5         int numberOne = input1.nextInt();
 6         System.out.println("请输入运算符:");
 7         Scanner input2 = new Scanner(System.in);
 8         String operation = input2.nextLine();
 9         System.out.println("请输入第二个数字:");
10         Scanner input3 = new Scanner(System.in);
11         int numberTwo = input3.nextInt();
12         int result = 0;
13         result = Calculator.getResult(numberOne, operation, numberTwo);
14         System.out.println("结果是: " + result);
15     }
16 }
17 
18 public class Calculator {
19 
20     public static int getResult(int numberOne,String operation,int numberTwo) {
21         int result = 0;
22         switch (operation) {
23             case "+":
24                 result = numberOne + numberTwo;
25                 break;
26             case "-":
27                 result = numberOne - numberTwo;
28                 break;
29             case "*":
30                 result = numberOne * numberTwo;
31                 break;
32             case "/":
33                 if (numberTwo != 0) {
34                     result = numberOne / numberTwo;
35                 } else {
36                     result = -9999999; //表示出问题
37                 }
38                 break;
39         }
40         return result;
41     }
42 }

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

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

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

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

       

 1 public class Calculator {
 2     
 3     public int getResult(int numberOne,int numberTwo) {
 4         int result = 0;
 5         return result;
 6     }
 7 }
 8 
 9 public class Add extends Calculator {
10 
11     @Override
12     public int getResult(int numberOne,int numberTwo) {
13         int result = 0;
14         result = numberOne + numberTwo;
15         return result;
16     }
17 }
18 
19 public class Sub extends Calculator{
20     @Override
21     public int getResult(int numberOne,int numberTwo) {
22         int result = 0;
23         result = numberOne - numberTwo;
24         return result;
25     }
26 }

 

 

 

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

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

       

 1 public class SimpleFactory {
 2     public static Calculator createCalculator(String operation){
 3         Calculator calculator = null;
 4         switch(operation){
 5             case "+":
 6                 calculator = new Add();
 7                break;
 8             case "-":
 9                 calculator = new Sub();
10                 break;
11         }
12         return calculator;
13     }
14 }

       客户端代码:

      

 1 public class UI {
 2     public static void main(String[] args) {
 3         System.out.println("请输入第一个数字:");
 4         Scanner input1 = new Scanner(System.in);
 5         int numberOne = input1.nextInt();
 6         System.out.println("请输入运算符:");
 7         Scanner input2 = new Scanner(System.in);
 8         String operation = input2.nextLine();
 9         System.out.println("请输入第二个数字:");
10         Scanner input3 = new Scanner(System.in);
11         int numberTwo = input3.nextInt();
12         int result = 0;
13         Calculator calculator = null;
14         calculator = SimpleFactory.createCalculator(operation);
15         result = calculator.getResult(numberOne,numberTwo);
16         System.out.println("结果是: " + result);
17     }
18 }

 

        这个时候,不管以后是想把这个功能用在pc端还是移动端或者其他位置,只需要修改相应的界面即可,而如果想要修改里面的功能(加法,减法等等)或者新增一些其他功能(求余,开方等等),只需要增加相应的子类,同时修改工厂方法中的switch语句即可(简单工厂模式也有其弊端,比如说太多运算的问题,就会重复上文所说的switch语句那个问题,此处只是为了举例说明)。

 

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

               

 

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

你可能感兴趣的:(一个对面向对象的理解的例子)