你的位置:首页 > ASP.net教程

[ASP.net教程]一个对面向对象的理解的例子


 

     少爷菜鸟一枚,求轻喷。

     

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

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

     

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