7.4 面向对象设计*

理解了面 向 对象的基 本 概念之后 , 就可以应 用 这些概念 来 进行面向 对 象 设 计(object-oriented design,简称 OOD)。 传统的程序设计方法是结构化的自顶向下设计,其思想是将软件系统分解为若干个功能,

每个功能都是对数据的一个操作过程。功能又可以划分为若干个子功能,如此反复分解下去, 直至每个功能所对应的操作过程显而易见为止。在分解功能的同时,还要考虑各功能之间的 接口。这种方法是以过程(函数)为中心的,每个函数都是一个黑盒子,函数调用者只需了 解函数的功能,无需知道实现功能的细节。

面向对象设计是以数据为中心来展开的。对于某种客观实体的数据,考虑可能施加在数 据上的各种操作,然后将数据和操作封装成一个黑盒子——对象。对象通过界面向外界提供 数据操作服务,服务的使用者只需了解服务接口,不必关心服务的实现细节。即使改动了对 象内部的实现细节,只要服务接口不变,所有使用该服务的程序代码就不需要改变。同样地, 对象作为服务提供者,也不需要考虑它的服务将被使用者如何使用,只需确保其服务能正确 处理数据即可。

因此,OOD 的中心任务就是设计各种对象,将对象的数据和行为用类定义出来。OOD 将一个复杂问题分解成一组相互协作的类,以类为设计单位可以大大减小设计的复杂性。

下面是 OOD 的一些指导准则。

描述问题

面向对象技术专家 G. Booch 提出了一种基于词性分析的设计方法,该方法要求设计人员 从目标系统的描述出发,通过问题描述中的名词和动词,来发现候选对象及对象方法。因此, OOD 的第一步是要建立待解决问题的准确、无二义性的描述。问题描述应该是自然、客观的, 不要加入人工的、主观的因素,这是因为面向对象思想的宗旨就是按客观世界的本来面目来 建模并开发应用系统。

找出候选对象

我们的目标是找出有助于解决问题的对象。从问题描述入手,找出问题描述中的名词, 然后逐个考察这些名词,看看是否合适作为对象。对象一般都包含一组相关数据项,如学生(包含学号、姓名、年龄等数据项)、课程(包含课程名、学分、教材等数据项)。而能用单 一数据表示的,或者只有单一行为的实体,一般不适合作为对象,如人数、姓名等。

注意,由于人类可以同时考虑和理解的问题数目受到大脑记忆和处理能力的制约,因此 认定的对象数目不宜过多。合适的对象通常是问题中自然出现的而非人工生硬构造的实体, 而且对象应该向外界提供足够复杂的服务。

确定对象的数据属性

对于认定的对象,接下来就该确定对象的数据。能确定为对象数据的信息一般都具有普遍性,即所有同类对象都拥有的数据,例如学生的学号和姓名。另外,对象数据必须对解决 问题有用,例如,学生的学号、姓名都是信息管理应用中必需的信息,而学生的发型可能就 与应用无关。注意,对象的数据可能是学号、姓名这样的基本数据类型值,也有可能是复杂 类型的值,甚至可能是另一种对象。例如,学生选修的课程也是属于学生对象的数据,课程 本身也是对象。

确定对象的行为属性

认定了对象及其数据之后,接着考虑对象需要什么操作。我们从问题描述中找出动词,它们通常描述了对象的行为。例如,“学生选修课程”中的“选修”就是学生对象的行为。对 象的方法通常使用动词来命名。

一类常见的方法是对实例变量的读取和设置方法。假设对象有实例变量 value,则通常应 提供 getValue 和 setValue 方法。这是因为对象数据是隐藏的,外界只能通过对象的方法来操 作对象数据。

对象的方法就是对象向外界提供的界面。界面不完善(如缺少某些方法)会使对象的使 用者无从完成工作,但也不是说向外提供的方法越多越好。对象的界面设计应当遵循恰好够 用的原则,即在能满足用户需要的条件下,界面越简洁越好。

实现对象的方法

有些方法用寥寥数行代码就能实现,有些方法则可能需要设计复杂的算法来实现。对于复杂方法,可以利用自顶向下逐步求精方法来设计。 在方法实现过程中,可能发现一个对象与其他对象之间的新的交互,这会提示我们为类增加新方法,或者增加新的类。

迭代设计

对于复杂程序设计,没有人能够一次性地顺利走过设计全过程。在设计过程中,经常需 要在设计、测试、增加新类或为现有类增加新方法等步骤之间循环往复。

应当多尝试替代方案,即使一个设计方案看上去不太灵,也可以沿着该方案的方向试着 前行,看看会导致什么结果。好的设计一定是通过大量试错而得到的,正是因为错误的设计 才使我们明白应该设计什么样的系统。

最后要指出,上述基于名词动词分析的 OOD 方法只是一个简单的策略,真正进行类的 设计时情况往往很复杂。究竟是否应当设计某个类并没有绝对的设计准则,经常依赖于设计 者的经验。和任何别的设计一样,程序设计既是艺术也是经验,可以通过不断的实践来掌握设计方法。

还要指出,对于小程序,OOD 一般起不了什么作用,说不定反而使编程变得麻烦。但当 编写的程序越来越大,类和对象就能很好地组织程序,减少代码量。