1
面向对象软件工程实践指南
1.2.6.2 6.2 对象模型的创建
6.2 对象模型的创建

6.2.1 类的识别

分而治之是人类处理复杂事物的重要手段,这也是软件开发中采用的重要手段。不同的方法学采用了不同的分解手段。传统的结构化方法是将系统按照功能进行模块分解,而面向对象方法学是按照类(对象)进行系统分解。因此,类的识别在面向对象软件开发中是一个基本任务。在实践中,许多开发人员从自己的偏好和经验出发进行对象识别,采用的方法过于随意,这将大大降低面向对象方法学的好处。

1)类的识别方法

按照面向对象方法学的理念,我们应该从实际问题中去找类,这种找到的类我们称为问题领域类,它主要是从实际问题出发,反映了实际问题中的业务实体、业务过程和业务概念。类的寻找有以下方法:

(1)文本分析方法:可以从用例文档中、特别是词汇表中找出那些意义重要的一般名词,它们是潜在的类。

(2)重用已有类概念:如果在该领域已经有一些软件,可以沿用该领域经常采用的类的概念。

(3)从动态模型中识别:在构建动态模型的过程中,可能会添加新的类。

2)类的类型

在识别类时,我们可以将类分为三种类型,分别为实体类、边界类和控制类。实体类代表了系统中需要跟踪的持久化信息实体,它是业务实体的直接代表;边界类负责用户与系统之间的交互,如系统窗口类;控制类代表了系统中的控制功能,它负责协调多个对象完成用例流程。三种类的UML表示方式如图6-1所示。

图6-1 边界类、控制类和实体类的表示

将类分为这三种类型体现了软件工程中“视图 模型”相分离的原则,实体类对应于“模型”,边界类对应于“视图”。模型对应于业务对象,是相对稳定的,而视图则可能变化比较多,通过分离,有效地降低了软件维护的成本。类的这三种类型也可以类比成一个企业内的组织分工,实体类就是那些岗位员工,是真正处理业务的;边界类就是那些销售和供应人员,负责与外界打交道;控制类是企业中的管理人员,本身不处理具体业务,负责协调前两类人员的关系。在一个分工合理的组织内,这三者都是需要的。

3)类识别注意点

在识别类的时候,有以下注意点:

(1)类的命名:在类命名时,首先应该用实际业务中的名字,同时,名字应该相对通用,而不是过早限定具体的方式。例如,在教室预订系统中,代表终端的类,可以是Mobile Terminal,也可以是 Mobile Phone,但 Mobile Terminal不限于 Mobile Phone,是不是客户端只支持Mobile Phone可以留待后续设计时决定,那么用Mobile Terminal就会比较通用。

(2)虽然我们一再强调类应该代表现实中的概念,然而我们毕竟在开发软件,所以在识别类时,可能会专门创造一些用来记忆“公共信息”的类,以避免信息的重复。例如,在现实生活中,每一件商品上都有商品信息如名称、产地、成分等,但是同类商品上的这些商品信息都是一样的,为了避免重复,我们可以添加一个Product Specification类,记录商品信息,Product类本身只保存商品编号、生产日期等信息,从而避免冗余的信息。

(3)在识别类时,也有可能依据软件的具体需要,适当添加一些实际生活中并不存在、但是出于软件的特点而添加的类,控制类就属于这种情景。

6.2.2 对象模型的表达

识别出类后,我们将利用类图来表示对象模型。类图由类和类之间的关联关系构成。分析阶段的对象模型主要是对真实世界中概念类的表示,而不是软件对象的表示。对象模型中要考虑下列因素。

1)属性的添加

每一个类需要添加属性,类的对象的属性取值保存和刻画了对象当前的状态。每一个类都有许多细节信息,因此可以作为属性的数据项也很多,但是,我们并不需要也不可能把一切数据项都作为属性,而是根据该属性对当前应用的价值来确定是否需要添加该属性。

另外一个问题是哪些应该作为属性,哪些作为类来建模。一般而言,属性应该是基本数据类型(如整型、浮点型、布尔型、字符串型)。如果一个属性是复杂数据类型(可以进一步分成多个数据项的数据),最好把它作为单独的类,然后将这两个类关联起来。

2)关联的添加

关联刻画了两个类结构方面的联系。那么,我们需要把所有可能的关联关系都刻画出来吗?显然并不必要。因为从某种意义上讲,世界上的万事万物都是关联的,小世界定理甚至告诉我们世界上任意两个人只要通过不多于六个中间人就可以联系起来。那么我们需要添加什么样的关联关系呢?以下为一些指南:

(1)添加那些重要的、需要持续一段时间的关联信息。

(2)添加那些能够表示聚合、组合这种“整体部分”关系的关联信息。

(3)在此阶段,我们只要从领域知识出发来考虑关联,并不需要考虑关联将来如何在软件中实现的问题。

(4)不要添加那些可以从其他关系中推导出来的关联关系。

完整的关联信息包括:关联的方向、关联的名字、多重性、角色。

3)对象模型的精化

对象模型的构建并不是一次完成的。我们应该对建立的对象模型进行多次重新检查并在必要的时候进行模型的调整。

在模型中可能会发现如下问题:

(1)重复的定义:由于我们通过多种渠道(如通过文本分析、构建交互图、依据领域知识等)去识别类,因此有时候可能将一个类重复定义了两次,或者将同一属性、同一操作定义了两次,就需要将它们进行合并。

(2)如何判别应该建模为类的属性,或者不必要作为类的属性:有些属性类型比较复杂,或者有相应的操作与其关联,那么最好将其建模为类;相反,有些类只有很少的属性,并且只有写入和读取的操作,那么就可以简化为属性。

随着分析的深入,可能会发现以下情况从而建立类之间的“泛化例化”结构:

(1)一个概念在现实中可以分成子类型,并且子类型具有不同的行为,那么可以将子类型建模成子类。但是值得注意的是,并不是在现实中的子类型都需要建模成子类,过于复杂的继承结构也会造成软件的复杂,因此只有在子类型对于应用有意义时,才需要建模成子类。

(2)发现多个类具有共同点,因此抽象出一个父类。通过抽象出的父类,并定义继承结构,可以增加重用,改善软件的可维护性。

判断两个类之间是否存在泛化例化关系时,有以下方法:

(1)百分百法则:父类的属性、方法和与其他类的关系可以百分百运用到子类上。

(2)IS A法则:如果Class A是Class B的父类,那么“Class B的对象IS AClass A”这句话就应该能读通。