首页 > 代码库 > 面向对象的重新思考

面向对象的重新思考

   

     在刚开始学习一门面向对象语言的时候,我们是这样写代码的:

     我们会先写一个小狗类,然后new它,最后调用它的方法实现功能。

 

          例如:

 

                   Dog d=new Dog();//造个小狗

                   d.shout();//小狗看到stranger会叫

 

        看得懂这段代码,说明你的面向过程语言基础学的不错~~~~~


      好的,这段代码先到这里,我们先来谈谈面向对象的特征:


1,抽象:

 

         首先想想我们在什么时候用到抽象?


         a.当我在设计一个系统的时候,我需要把一些东西归类,比如,小狗,小猫,这些都会做一个animal类,然后让小狗小猫继承这个animal.这是基本的类抽象

 

         b.还有一类抽象,比如我们写个接口,让一个类去实现这个接口,这是接口的抽象;(抽象类的抽象和接口的抽象是一样的,都没有方法体,都要子类去具体实现);

 

        c.类的成员变量使用超类或接口:

 

       当某个类作为另一个类C的成员变量的时候,而这个子类又有诸多变化,这时我们就要考虑将这个变化的部分做成多个子类,并且将这多个子类抽象出来一个父类,将这个父类作为类C 的成员变量。


        比如,我现在有个很多收费策略,然后在类C中有一个要调用计算收费的方法,但是因为调用时的诸多情况,我必须在调用时动态确定使用哪种收费策略,所以,在定义这个C的成员变量时,我们就要使用抽象出来的父类了,即为众多的策略定义一个父类或接口。


       这时情况又和上面的小猫小狗的情况一样了。而且预先设计中的抽象和重构方法时的抽象目的是相同的,都是为了系统的扩展性,易修改。

 

        总的来看,抽象起到了一个概括的作用,就像拿着一条摸起来凉凉的,张的长长的,吐着舌头的东西问你,知道这是什么吗?你不确定这是哪种蛇,但是,你会非常肯定的回答:这是条蛇!这样的回答虽然不准确,但是却给了你百度的时间,等你百度过后,你就可以说:这是条@#$@#蛇。。。。


   



 

2,封装

 

      封装能带来什么好处呢:


       1,首先,想想你使用过的实体类,你能很快写出这个是学生的ID,这个是教师的ID。。。这里,封装实体的数据,起到了一个打包的作用,将属性绑定到了类上,方便查找和使用,上面列举的是对于属性的封装。类中也有方法啊,所以,同样,也有方法的封装。

 

      2,回想设计模式,有些对象的创建过程我们是无需参与的:例如,在单例模式中,我们将类之创建一个实例的过程交给类本身来处理,将类的创建封装在了类里面,避免了创建多个实例; 还有我们熟悉的各种工厂模式,我们将对象的创建迁移到了具体的工厂类里面,去除了选择问题。

 

       3,对类行为的封装

回想一下命令模式,我们把各个命令做成类,将请求操作的对象和执行操作的对象分开了,接触了这里的紧耦合。

 

 

3,继承

 

      在面向对象的设计中,我们是免不了使用继承的,首先,来看一下公认的使用继承带来的那些好处:

 

     a.基本好处:

          可以继承父类的属性和方法,获得父类的行为。例如,我们在使用模板方法的时候,将重复的东西都放到父类,子类只需在继承父类的基础上做一个很小的变更就ok了。

 

    b.通过继承达到“类型匹配”




  



     在装饰者模式中,我们让服饰类去继承people,这在现实中是不可理喻的,但是在设计中,正是通过这个继承,让我们可以在形象展示中层层调用父类的方法,达到一个装饰的效果。感觉这个模式设计的非常酷!!!

 

 

     但是,继承的后果你想过吗?

 

      1,多继承的后果:C++强大的多继承为代码的复用提供了很大的方便,但是也带来了很多问题,比如多继承的二义性问题,还有继承关系的混乱问题;

 

      2,为了复用而使用的继承会给维护增加的子类带来困难,因为子类很可能不具有它从父类继承的方法,而且它也无法屏蔽从父类里面继承的方法。就像是富二代老爸想给儿子安排接手自己公司可是儿子却偏偏想去玩儿音乐。如果子类不需要父类的方法或者根本不能去实现父类的方法,这就让继承关系带来了一个非常尴尬的事情。

 

 

       面对继承可能带来的后遗症,所以,我们才才有了后来的提倡使用组合取代继承。

 

 

4,多态

 

    如果说面向对象为什么可扩展性这么强,而且非常灵活的原因,感觉多态起了很大的作用。

 

    首先,回到我们开始的小狗的问题上:

 

         Dog d=new Dog();//造个小狗

         d.shout();//小狗看到stranger会叫

 

 

      如果有一天,我不想听小狗叫了,我想听猫叫了,这时,可能我们会这样写:

 

           //Dog d=new Dog();//造个小狗

           //d.shout();//小狗看到stranger会叫

 

           Cat c=new Cat();

           c.shout();

 

       但是,过了两天,我又想听鸡叫了,这时,你可能又把小猫的代码注释掉,改成鸡叫的代码,但是,作为一个程序员,你要认识到,一段相似的代码写到第三遍了,那么一定是设计的有问题。

 

      这时,多态的作用就显示出来,这也是为什么在编程中一直强调的写法:将父类的引用指向子类的对象。

 

       如果我们使用了这种写法:

 

             Animala=new Cat();

             a.shout();

 

        那么,我们日后的变更将更加方便,当我们要变更具体的实现的时候,只要稍加改动就好啦!

    

        另外,还有重写,重载等多态的表现,但是还是觉得上面的最经典。

 

 

 

PS:最近在学习Java+Head first,感觉这是我真正迈入面向对象大门的开始~~~

 


面向对象的重新思考