大二下学期才开设“面向对象原理与语言”这门课,很荣幸遇到一位大师级的老师。他所传授的知识与思想不受教材,大纲的限制,培养出了大批优秀的工程师。现在我把自己所学的知识根据他的讲义记录下来,以便将来回顾与复习。不足之处,还请大家多多指教。
老师的教授方式有点特别,他给我们选择的教科书为《Java核心技术》与《Java编程思想》,他认为他应该教授我们的为Java的核心技术与思想。对于Java的语言规范,这都属于基础知识,他不愿意过多教授,因为我们有C语言的基础,这方面更应自行学习。同时,他多次告诫我们,我们实际所学习和关注的不是Java语言本身,从Java语法去学习Java很难达到比较高的高度,我们更应该重点关注面向对象的思想,并且从操作系统和内存角度来认识Java(任何语言功能的实现都要与操作系统联系并回归内存)。
机器语言 ---〉 汇编语言 ---〉面向过程(C语言) ---〉 面向对象(Java语言)
以上是语言的发展演变(尽管在面向对象的基础上又出现了类似面向服务的软件构造方法,但是这里的重点是面向对象)
(一) 面向机器:(了解)
面向机器的语言关注机器本身的操作指令、存储等底层硬件的细节。
面向机器的代码由机器直接执行,速度快,但是编写、维护非常困难,编写效率十分低下。
由于二进制的机器语言实在是太难编写了,于是就发展出了汇编语言。汇编语言采用助记符来编写程序,提高了机器语言的可读性
面向机器的语言包括二进制的机器语言和采用助记符的汇编语言
(二)面向过程:
程序 = 算法 + 数据结构
特点:以算法为主,算法和数据结构分离
算法 = 流水线,数据结构= 原料/中间产品,程序 = 产品
即使我们使用面向对象的语言进行开发,最后转换为CPU能执行的指令,也还是面向过程的
注释:任何语言功能的实现都要回归内存,同时注意关注面向过程与面向对象的算法和数据结构的联系。
面向过程的语言不再关注机器本身的操作指令、存储等方面,而是关注如何一步一步地解决问题,即解决问题的过程。大大减轻了程序员的负担,提升了程序员的工作效率。
面向过程采用结构化程序设计指导思想。
结构化程序设计方法主要由以下三种基本结构组成:
1)顺序结构:顺序结构是一种线性、有序的结构,它依次执行各语句模块。
2)循环结构:循环结构是重复执行一个或几个模块,直到满足某一条件为止。
3)选择结构:选择结构是根据条件成立与否选择程序执行的通路。
采用结构化程序设计方法,程序结构清晰,易于阅读、测试、排错和修改。由于每个模块执行单一功能,模块间联系较少,使程序编制比过去更简单,程序更可靠,而且增加了可维护性,每个模块可以独立编制、测试。
分析时采用问题分解的方法:自顶向下、逐步求精、模块化。直到分解的小问题可以用代码实现来解决为止。
实现时采用的方法:自底向上、逐步实现、模块化。直到问题解决。
面向过程的语言包括C语言、BASIC语言等。
注释:注意关注面向对象和面向过程的分解方法。
(三)面向对象:
程序 =(数据结构+算法)对象 + 交互
特点:以数据结构为主,算法和数据结构封装在类中。
(上面应该与面向过程进行对比一下)
第一次软件危急主要体现在“复杂性”方面(结构化程序设计),第二次软件危机面(面向对象程序设计)对快速多变的业务需求主要体现在“可扩展性”、“可维护性”方面。
面对快速多变的业务需求,传统的面向过程方法已经越来越不能适应。面向对象的思想开始流行起来。面向对象只是一种新的软件方法而已。
(四)面向对象与面向过程的区别:(通过举例进行认知)
面向过程是一种以“过程”作为中心的编程思想,面向过程采用问题分解,就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象是一种以“对象”作为中心的编程思想,面向对象采用对象分解,是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
例如五子棋,面向过程的设计思路就是首先分析问题的步骤:
1、开始游戏,
2、黑子先走,
3、绘制画面,
4、判断输赢,
5、轮到白子,
6、绘制画面,
7、判断输赢,
8、返回步骤2,
9、输出最后结果。把上面每个步骤用分别的函数来实现,问题就解决了。
而面向对象的设计则是从另外的思路来解决问题。
整个五子棋可以分为
1、黑白双方,这两方的行为是一模一样的,
2、棋盘系统,负责绘制画面,
3、规则系统,负责判定诸如犯规、输赢等。
第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的i变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。
通过对比:
可以明显地看出,面向对象是以功能来划分问题,而不是步骤。
同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。
功能上的统一保证了面向对象设计的可扩展性。比如我要加入悔棋的功能,如果要改动面向过程的设计,那么从输入到判断到显示这一连串的步骤都要改动,甚至步骤之间的循序都要进行大规模调整。如果是面向对象的话,只用改动棋盘对象就行了,棋盘系统保存了黑白双方的棋谱,简单回溯就可以了,而显示和规则判断则不用顾及,同时整个对对象功能的调用顺序都没有变化,改动只是局部的。
再比如我要把这个五子棋游戏改为围棋游戏,如果你是面向过程设计,那么五子棋的规则就分布在了你的程序的每一个角落,要改动还不如重写。但是如果你当初就是面向对象的设计,那么你只用改动规则对象就可以了,五子棋和围棋的区别不就是规则吗?(当然棋盘大小好像也不一样,但是你会觉得这是一个难题吗?直接在棋盘对象中进行一番小改动就可以了。)而下棋的大致步骤从面向对象的角度来看没有任何变化。
当然,要达到改动只是局部的需要设计的人有足够的经验,使用对象不能保证你的程序就是面向对象,初学者或者很蹩脚的程序员很可能以面向对象之虚而行面向过程之实,这样设计出来的所谓面向对象的程序很难有良好的可移植性和可扩展性。
面向过程 :
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:扩展比较麻烦。没有面向对象易维护、易复用、易扩展
面向过程的流程和原料相对固定,每次需求的变更,可能都要对流程的每个步骤、原材料、中间产品进行修改,扩展比较麻烦。
应用范围:性能要求很高的、需求相对稳定的专用系统。
对性能要求很高的专用系统软件,如操作系统、数据库、协议这些基础软件一般需求都比较稳定(相对稳定,并不是不变)。所以操作系统、驱动程序、网络设备程序等专用系统,基本上都是用C语言编写的。
运行性能:面向过程程序本身的性能会影响专用系统的性能。
面向对象 :
面向对象思想的核心是“可扩展性”(这句话非常重要!!!)
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加易于维护和扩展。(思考易维护、易复用、易拓展是怎么实现的?)
缺点:运行性能可能比面向过程低
应用范围:复杂的、需求多变的系统
对于复杂应用软件,如企业应用、互联网、游戏等,需求经常变化,功能不断扩展。而面向对象的思想的核心是“可扩展性”,所以经常变化的地方就是面向对象的应用方向。
运行性能:面向对象不会导致应用系统性能的降低。
1)C程序本身一般比Java程序快(只是一般)
2)运行Java字节码程序的JVM虚拟机,可以进行动态优化,来提高面向对象程序本身的运行效率。
3)对于应用软件,都是复杂的系统,这些应用系统都要和存储系统(磁盘、磁带等)打交道,要通过网络进行交互,要访问数据库…… 。应用软件的运行性能是一个综合性能,语言本身性能的提升,在整个应用系统流程中占比非常低,对应用系统的性能的提升几乎没有影响。
所以,对于复杂的业务系统来说,性能的好坏是由设计来决定,而不是由语言来决定的,更不会因为采用了面向对象而导致性能的降低。
提示:
1)面向对象编程思想/面向过程编程思想
2)面向对象语言/面向过程语言
3)面向对象程序/面向过程程序
面向过程、面向对象是一种编程思想、是一种思维方式、是一种思考问题的方式,与具体的语言没有关系。
C语言是纯粹的面向过程的编程语言,Java语言是纯粹的面向对象的编程语言。
注意:面向对象是一种思想,和语言本身没有多大的关系,只是一些语言比如C++Java C#等,面向对象编程更加方便,也有更多的特性。用C 同样也可以写出面向对象风格的程序,linux源码里面都有很多类似的用法,但是你可能会觉得很别扭,因为这样的实现都需要用到回调函数。所以说处理不同的问题要选用合适的工具。