很明显的一点就是编码的思维方式大大的不同:
面向过程是从计算机处理问题的流程和步骤出发,先做什么后做什么,整个非常清晰流程结构。
面向对象则从人们抽象分析现实事物出发,对客观世界的建模。
也就是说前者偏向于机器思维,而后者偏向人类思维。显然后者应当更自然更具有亲和力。
同时从软件工程的角度看。在分析阶段,面向对象可以结合UML工具(比如类图)做有效分析;在编码阶段,利用封装的特性进行安全的编码,利用继承的特性减少代码的冗余;在后期维护阶段,那么设计良好的软件结构将最大的减少代码的改动。(我们不是害怕修改代码,而是害怕修改了这部分代码会对其它代码产生什么样的影响;也就会引入新的BUG)
讲一个常见的例子来阐述面向对象: 一个容器里(_container)面放着若干个形状的物体(_shape)(比如有:Circle, Rectangle),现在要把它们画出来(Draw)。按照面向过程的方法写一个总框架: foreach( _shape in _container ) { switch( type of _shape ) { Circle: Draw_Circle(_shape); Rectangle: Draw_Rectangle(_shape); } }
很简单的面向过程写法,几行代码搞定,不存在任何问题。不过现在没问题不代表将来没问题,问题总是出现在产品的不断改进之中,比如现在要增加一种新的_shape: Eclipse。 那么我们就需要加代码了,首先要增加Draw_Eclipse(),但是还不够,还需要修改总框架,增加相应的switch处理。(而BUG往往在此时产生,经常改了一处而忘记修改另一处)。
但是,如果采用面向对象呢,情况如何?首先框架的代码只要这样: foreach( _shape in _container ) { _shape.Draw(); } 然后实现每一类对象: _circle extend _shape { Draw() { //draw a circle } };
_rectangle extend _shape { Draw() { //draw a rectangle } };
如果需求发生变更,要增加一种新的_shape: Eclipse,那么只要增加一处的代码,就是该类的实现即可,不用修改总框架(减少BUG的出现机率) _eclipse extend _shape { Draw() { //draw a eclipse } };
这就是通过面向对象实现的一种可扩展可维护的简单模型。同时也阐述了对象的核心意义:每个对象对自己的行为负责,而不需要框架代码来负责。
|