本文是关于面向对象思维过程系列文章的第一部分,选择这个主题作为书籍或专栏的标题是一个重大的决定,做出这个选择并不简单,因为已经有很多面向对象主题的好书和文章了,包括面向对象分析、面向对象设计、面向对象编程,设计模式、面向对象的数据库、统一建模语言(UML)、不同的面向对象编程语言以及其它许多面向对象的主题。
但读完这些书之后,许多人忘记了这些主题都是建立在一个基础之上的:你是如何思考面向对象方法的。不幸的是,许多软件专业人员花费了大量时间在这些书中,但却没有努力真正理解包含在它们之中的思想。
我主张学习面向对象思想时不是靠学习一个特定的开发方法或一套工具来完成的,面向对象做事的方法是一个简化表达的思维方式,本专栏所有文章都是与面向对象思维过程有关的。
从面向对象思维过程中将开发方法和工具分开不是一件容易的事情,许多人都是通过一个开发方法或一个开发工具引入面向对象的思想的,许多C程序员都是通过向C++移植才接触面向对象的思想的,还有一些软件专业人员是使用UML表达对象模型时才接触到面向对象思想的。
理解学习面向对象思想和使用支持范例的方法和工具之间的重要不同之处是很重要的,在这篇文章中,Craig
Larman表述了“UML是什么,不是什么”。
不幸的是,按照软件工程和UML图形表示语言的背景,学习阅读和编写UML标记的技巧看起来就和面向对象分析和面向对象设计差不多,当然,这并不是面向对象,后者比前者重要得多,因此,我建议学习面向对象分析和设计的技巧,它比UML标记或使用一个用例工具重要多了。
虽然学习一门建模语言是很重要的一步,但首先学习面向对象技巧更重要,在没有面向对象思想之前学习UML就和没有一点电气知识就去学习如何阅读一个电气图有点类似。
相同的问题发生在选择编程语言,正如前面谈到的,许多C程序员是通过移植C++而接触到面向对象思想的,通常,C++开发人员只是使用C++编译器的C程序员。
即使面向对象语言如Java、C# .NET和Visual Basic .NET已经变得非常流行,但这个问题仍然存在,有许多Visual
Basic程序员现在必须跳跃到Visual Basic .NET,同样,也有许多C++程序员可能被迫执行面向对象的实践,被要求转移到Java或C#,除了思考面向对象的方法外他们没有别的选择。
早期的Visual Basic不是面向对象的,C++也是向后兼容C,正是因为如此,就出现了大量的使用C++编译器,但同时只使用了C语法的情况,放弃了所有C++面向对象的特性,更糟糕的是,一个使用了足够多面向对象特性的程序使得程序难以理解,这就是对面向对象思想的滥用。因此,当你在使用面向对象的开发方式时,首先学习面向对象思想的基础显得非常重要,不要受到编程语言(如C++,C#或Java)或建模语言(如UML)的影响,多花点时间学习面向对象的思维过程。
当我在1980年末上我的第一堂Smalltalk课时,老师说这堂课是一堂全新的面向对象范例的思维方法,它接着说即使我们大多数人都是非常优秀的程序员,但我们中肯定有大约10%到20%的人永远都不会掌握面向对象的思维方式,如果这种情况确实属实,很有可能是那部分人从来都没有花时间研究范例和学习面向对象思想。
本专栏的范围
现在应该非常清楚了,在一头扎进编程语言和建模语言之前,先成为面向对象思维过程的忠实信徒吧,专栏内容将会包括Java、C#和VB
.NET代码示例,同样也会有UML图表,但真正理解面向对象思想时,你不需要知道Java、C#或UML。我已经说过,首先应学习思想,为什么要那么多代码或UML图表呢?首先,它们都是描述面向对象思想的好工具,第二,它们对面向对象过程都非常重要,关键是不要集中在代码或UML,而是使用它们来理解这个思想。
并不是这个专栏就不教代码语法或UML了,我希望通过这个专栏让你对其它面向对象主题引起兴趣,如面向对象分析、面向对象设计和面向对象编程。
面向对象思想介绍
其实面向对象软件开发早在1960年就开始了,这多少让人感觉意外,虽然对象在目前的软件行业变得更加流行了,但大量的软件厂家还在拿面向对象表演,其实在软件行业它已经没什么秘密可言了,目前有大量传统的非面向对象的系统看起来工作得非常好,为什么要冒险替修改它们呢?大多数情况下,你不应该修改它们,至少不要简化修改的理由,使用非面向对象的代码编写的系统天生并没有什么错。
过去10年面向对象开发呈现逐步增长的趋势,Web的出现打开了一个全新的舞台,开发Web程序可以完全不受传统思维的影响,即使受到传统思想的束缚,也趋于将传统系统封装成对象。
对象封装
对象封装是面向对象代码,包括内部结构代码,例如,你可以编写一个结构化模块,然后将其封装到对象中,让它看起来就像一个对象。
随着Java的成功和.NET技术的引入,对象正成为信息系统的主要组成部分,随着互联网的爆炸式增长,电子高速公路正变成面向对象的高速公路,业务逐渐转移到Web上,它们也正向对象移动,因为未来Web使用的大多数技术都是面向对象的。
本文剩下的部分将对面向对象基础做一概述。
面向过程编程 vs 面向对象编程
在我们深入研究面向对象开发的优点之前,我们先思考一个更基础的问题:对象究竟是什么?这是一个既复杂又简单的问题,复杂是因为要全部重新转变思维,这不是一件容易的事情,简单是因为大多数人已经思考过对象这个术语了。
例如,当你看一个人时,你会将这个人看做一个对象,一个对象由两个术语定义:属性和行为。人有属性,如眼睛颜色,年龄,身高等,人也有行为,如走路,说话,呼吸等。在它的基础定义中,对象是一个包括数据和行为的整体,这就是传统的面向过程编程方法和面向对象编程方法之间的最大不同。
在面向过程编程中,代码统统放在不同的函数或过程中,如图1.1所示,这些过程然后变成“黑盒”,通过它进行输入输出,数据放在独立的结构中,由这些函数或过程维护。
图1.1 黑盒
面向对象和面向过程的不同之处
在面向对象设计中,属性和行为都包括在一个对象中,然而在面向过程编程或结构设计中,属性和行为是分开的,这是面向对象和面向过程编程之间最大的不同。
自青铜器时代以来,面向过程编程已经成为主流,因此,为什么还要改变呢?首先,如图1.2所示的那样,在面向过程编程中数据和过程是分开的,有时数据是全局的,因此很容易超出你的范围修改掉数据,这意味着对数据的访问是不能控制的,也是不能预测的,如多个函数访问相同的全局数据,第二,因为你不能控制谁可以访问数据,测试和调试变得非常困难,通过使用对象将数据和行为集成在一起就可以解决掉这些问题。
图1.2 使用全局数据
无全局数据
当设计优良时,可以保证在面向对象模型下不会存在全局数据,这个事实在面向对象系统中提供了大量的数据集成。
对象比原始数据类型如整数和字符串更多,对象包括了实体如整数和字符串,它代表属性,还包括了方法,它代表行为。在一个对象中,你使用方法操作数据,或许更重要的是,你可以控制对象中成员的访问(包括属性和方法),这意味着其中一些成员,如数据类型和方法,对其它对象可以隐藏起来,例如,一个叫做Math的对象可能包括两个整数,分别是myInt1和myInt2,math对象很可能也包括必要的方法,以便设置和检索myInt1和myInt2的值,它还可能包括一个方法Sum()来计算两个整数的和值。
面向对象术语
在面向对象术语中,数据相当于属性,函数相当于方法,对属性和/或方法的限制访问叫做数据隐藏。
通过在同一实体中集成数据和方法,在面向对象术语中叫做封装,我们可以控制对Math对象中的数据访问,通过定义这些整数禁止使用,其它逻辑上非连接的对象就不能操作math对象的myInt1和myInt2整数。
面向对象设计
记住如果创建设计不好的类是不能限制对类属性的访问的,底线是你可以设计差的代码,但面向对象设计却不能马虎,务必坚持听设计指导课,我们将在未来的文章中涉及这些问题。
当另一个对象如myObject想获得myInt1和myInt2的访问权究竟会发生什么?它询问math对象:myObject向math对象发送一条消息,图1.3显示了两个对象之间如何通过它们的方法进行通信,消息其实是调用math对象的sum()方法,sum()方法返回值给myObject,美妙之处是myObject不用知道求和是如何计算的,在这个例子中,你可以修改math对象如何计算求和,不用修改myObject,所有你所想的就是求和,你不用担心它是如何计算出来的。
图1.3 对象间通信
计算求和不是myObject的职责,而是math对象的职责,只要myObject有math对象的访问权就可以了,它可以发送一条合适的消息并获得一个返回结果,通常,一个对象不能操作另一个对象的内部数据,即myObject应该不能直接修改myInt1和myInt2的值。同样,值得注意的还有,最好构建一个小的任务单一的对象,而不要构建一个大而全的大对象。
结语
在这面向对象思维过程系列文章的第一篇中,我们涉及了一些关于面向对象的基础知识,并简要介绍了一些面向对象的思想,在下一个专栏中,我们将定义一些面向对象的基础知识-对象是什么?
|