把数据和过程这两个逻辑上独立的实体组合在一个逻辑体(对象)中,对象与对象之间只能通过发送消息来进行联系。这样,使原来各种类型的数据和数据结构与起不同作用的过程之间,非常复杂的关系大为简化,从而使软件的设计效率↑,可靠性、可读性、可维护性↑。同时由于各个对象是独立的,只通过消息传送进行联系,所有对象既可以在单机上运行,也可以同时分配给多个处理机执行,充分利用多处理器(机)并行所带来的好处,有效地支持并行处理。
凡是思维的建立都要靠练习。你要建立完整的面向对象思维,就得通过完整的面向对象的程序的开发来练习。我写了这么多年程序,发现最符合这一点的就是——你自己去造一个GUI库。等你造到你觉得满意了,很多年过去了,面向对象的思维早就烂熟于胸,化为本能。
假设我们是上帝,要创造世界,因为这个过程太过复杂,无从入手,所以先从一件简单的事情看起。现在我们要设计一个方法,用于描述狼吃羊这个事情,某只狼吃了某只羊,你可以面向过程地吃,eat(狼A, 羊A),也可以面向对象地吃,狼A.eat(羊A)。差别在哪里?只是写法有点变化。
好,那么我们帮上帝模拟整个生物界,这里面很多东西可以吃,大鱼吃小鱼,小鱼吃虾米,吃不吃皮,吐不吐骨头,这个时候再来修改这个eat函数,复杂吗?eat里面要判断很多东西,假如上帝很勤劳,所有代码都自己设计,那没关系,没太大区别,判断就判断呗。
假设上帝没足够精力来管理整个东西了,雇了一群天使来协助设计,每个人都来修改这个eat函数,当然可以拆分,wolfEatSheep(), tigerEatWolf(),然后在eat里面判断参数来分别调用,把函数分下去让每个人做,可以。
动物不光要做吃这个事情,要能跑能跳,会说会叫,又多了一堆函数,每个里面都这么判断,相当相当的烦。怎么办?我们来面向对象一下。
现在开始按照动物拆分,100个天使,每个天使创造一种动物。创造哪种动物,就站在哪种动物的角度考虑问题,我吃的时候怎么吃,跑的时候怎么跑,都跟别人无关,这么一来,每个人就专注多了。每个动物只关注我要怎么才能活着,不必站在上帝的角度考虑问题。这个过程,是类的划分过程,也就是封装的过程。
这时候,上帝觉得自然界光有动物是不行的,还要有植物,刚才说的这些都是动物,植物的特点跟动物有很大区别。假设你是上帝,为每种生物安排衣食住行,那是相当复杂的。偷懒吧,上帝说,植物们,你们自己生长吧,动物们,你们吃喝玩乐吧,假如能达到这个效果,那很省事。
上帝用一个循环来遍历所有动物,让他们吃喝玩乐,用另外一个循环让植物欣欣向荣。动物跟植物为什么要区别对待?因为它们不是同样的东西,能做的事情不同。所有动物派生于动物这个基础类型,从动物这个种类下,又分出各种纲,各种目,各种属。狮子是哺乳动物,猴子也是,但是狮子是猫科动物,猴子是灵长动物,这就构成了一个倒着的树状体系,一层一层形成继承关系。哺乳动物会喂奶,那么所有继承自哺乳动物的,都自动拥有这个特征。整个这一切,构成了继承链。
假设有一天由于变异出现了新物种,不必劳烦上帝关照,只要鉴别一下它属于什么类型,就知道能做什么事了,它的一举一动,都必然拥有它所继承的种类的特征。
这样就能描述生物界了吗?不,还有那么一些怪胎的存在。你认为哺乳动物都不会飞,那就错了,因为蝙蝠会飞。蝙蝠会飞是它自身的特性,并非继承自哺乳动物,但是“飞”这个动作,却非蝙蝠独有。如果把“飞”定义成接口,那就很美好了,蝙蝠实现了它的飞行接口,虽然内部实现跟鸟类有所不同,而且这并不影响它的哺乳动物特性。
总之,是否面向对象只是思维方式的不同。做一个软件,面向对象也能做,不面向对象也能做。我的观点,如果关注可维护性和协作性,从目前的角度,面向对象是很好的选择,它很自然,很优雅,优雅得只要打一个“.”,你就能想起来什么事能做,什么事不能做。
把数据和过程这两个逻辑上独立的实体组合在一个逻辑体(对象)中,对象与对象之间只能通过发送消息(调用)来进行联系。
这样,使原来各种类型的数据和数据结构与起不同作用的过程之间,非常复杂的关系大为简化,从而使软件的设计效率↑,可靠性、可读性、可维护性↑。
同时由于各个对象是独立的,只通过消息传送进行联系,所有对象既可以在单机上运行,也可以同时分配给多个处理机执行,充分利用多处理器(机)并行所带来的好处,有效地支持并行处理。
简单比较两种思维,把一个问题的解决,面向对象设计程序思维是:是哪些人的责任构成。而面向过程的思维是:这个问题到底需要做什么。