Delphi 中面向对象编程之我见
面向对象的编程技术提出来也有些年头了,开发大型软件的时候采用面向对象的编程技术可以缩短程序的开发周期,提高程序的可读性,易调试性,同时也就相应的提高了程序的可维护性,而对大型软件而言,可维护性是保证其生命力的一个极为重要的指标。
不知大家注意到没有,可视化程度很高的编程语言在采用面向对象的编程技术上很难处理。例如 VB,4.0基本不支持面向对象的编程,5.0 好一些,但微软也只敢说在面向对象的编程上 5.0 比 4.0 好得多,而不敢说 5.0 支持完全的面向对象的编程(6.0 我没用过,不知道,如果能支持,也是 VB 爱好者的福音了)。这大概就是人们常说的不用 VB 做大型程序的重要原因之一吧。 我不知 Delphi 是从什么版本开始提供面向对象编程支持的,但我从 VB 5.0 转到 Delphi 4.0,除了项目要求外,这是最重要的原因了。
由于 Delphi 除了支持面向对象的编程外,也支持一般的面向过程的编程,而且因为其可视化技术的运用,很多人(包括我)很容易就偏离了面向对象的方向,实际上,我觉得要实现面向对象的编程也不难,因为 Delphi 给你的全都是对象,你只要在编程的时候注意自己的代码就是了。下面是我对在 Delphi 中采用面向对象技术的一些体会:
1.不要用全局变量
即使要用,也要用全局对象来代替它。习惯了面向过程编程的程序员在这点上很容易犯错,而且这一点相对来说也比较难掌握。实际上,全局变量也是面向过程编程技术的一个很大的缺陷,难跟踪,难调试,也就难维护。
为什么要用对象而不是变量呢?对象可以封装对变量的操作,任何对该变量的操作都必须通过调用对象的方法来完成,我们可以在操作该变量的方法中设置断点来调试,这就解决了前面所提到的 3 个难点(难跟踪、难调试、难维护)。
举个常见的例子(也许并不能最大限度的反映这个问题):让你做一个 IE,对于 Internet Option,你打算怎样处理?
根据以上的讨论,我的想法是写一个 TDefaultINI 类,这个类负责 Option 中各项设置的保存,读取。Option window 和别的需要操作其中设置的对象都通过这个类来进行处理。这样就实现了数据的封装。你可以定义一个 TDefaultINI 类的实例作为全局对象,当然,因为这些设置是保存在存储器中可以随时读取的,你也可以只在需要的时候创建一个 Tdefault 对象来完成你的功能。
2.对象之间交换数据,尽可能的使用属性而不是变量
为什么要用属性而不是变量呢?对数据的操作可以通过属性的方法进行封装,一旦以后对象内部的数据结构发生了变化,只要我们提供的属性接口不变,对程序别的部分的影响就能减小到最小。例如 Form 之间通过属性来交换数据。以后因为某个原因你得将原来用数组实现的东西改为用链表实现,只要你的属性接口仍然是数组,那对别的对象就几乎没有影响。
3.合理的安排对象的方法
我直接举例来说明这个问题,例如在连接数据库的时候,你是在主 Form 中设置好 TdataModule 中 Tdatabase 的 AliasName 和 Params,然后用 DataModule.Database.Open 来连接呢,还是写一个 TdataModule.ConnectToDatabase 方法,将 AliasName 和 Params 作为 TdataModule 的属性,而在主 Form 中调用这个方法来连接呢?从理论上来讲,两种方法都是面向对象的。也许很多人不能体会到后一种方法的优越性,想象一下如果数据库发生了变化,以前只有 Sql Server,现在还需考虑 Oracle。后一种方法将会使你的应对轻松的多,尤其是你在主 Form 中有好几处地方需要连接数据库的时候。
4.合理的安排你的对象
一个问题该有几个对象来解决,每个对象实现什么功能,它们之间是什么联系?这个问题是面向对象编程的永恒的问题,Delphi 中这个问题怎么处理呢?在此我就和 Form 有关的问题和大家讨论一下吧,先举一个例子:写一个将 IE 中的收藏夹导入到数据库中的程序,该怎么安排你的对象?这个问题并不复杂,一个 Form 就能解决问题了,也许为了数据库管理比较方便,再加上一个 DataModule,Form 负责读入收藏夹,将之显示在 TreeView 中,用户可以选择 TreeView 的节点(即收藏夹)导入数据库。也许你的程序刚做好,老板又要求对 NetScape 的 BookMark 也完成同样的功能,怎么样,你的改动量有多大?如果你以前使用的是两个对象来完成上面讨论的一个 Form 的功能,一个对象负责将收藏夹的数据导入到 TreeView 中,而 Form 只完成对 TreeView 的操作,你就会发现你的改动是很轻松的。由此我的建议是 Form 只完成对界面的操作,对于具体的数据结构,由我们自己写的对象去完成。
5.不要在两个同级的子 Form 之间交换数据
在 Delphi 中很容易犯这个错误,这样做是很危险的,因为很有可能你认为存在的 Form 被关闭了或者干脆就没有打开过,而且这样做最大的坏处是程序晦涩难懂。解决的办法之一是可以通过它们的父 Form来交换数据,例如父 Form 中取得 A子 Form 的属性值,根据这些值来设置 B 子 Form 的属性值。
面向对象的编程技术绝不只是应用在大型软件的开发上,实际上,小型程序采用面向对象的技术开发对于今后的扩展和移植(即是只是部分功能的移植)是很有帮助的。希望我的这篇文章能起到一个抛砖引玉的作用,欢迎大家和我讨论,我的 email :l940801@yahoo.com。