您好,欢迎访问三七文档
第8章类图和对象图系统的静态模型描述的是系统所操纵的数据块之间持有的结构上的关系。它们描述数据如何分配到对象之中,这些对象如何分类,以及它们之间可以具有什么关系。静态模型并不描述系统的行为,也不描述系统中的数据如何随着时间而演进,这些方面由各种动态模型描述。对象图和类图是两种最重要的静态模型。对象图提供了系统的一个“快照”,显示在给定时间实际存在的对象以及它们之间的链接。可以为一个系统绘制多个不同的对象图,每个都代表系统在一个给定时刻的状态。对象图展示系统在给定时间持有的数据,这些数据可以表示为各个对象、在这些对象中存储的属性值或者这些对象之间的链接。理解系统的一个方面是了解哪些对象图表示了系统可能的有效状态,哪些对象图表示的是无效状态。例如,考虑图8.1所示的两个对象图,它们描述一个假想的大学档案系统中的学生和课程对象。图8.1有效对象图(a)和无效对象图(b)图8.1(a)显示的是一特定学生选修一门课程的情形。假设系统的责任之一是记录哪些学生选修哪些课程,那么这个对象图就表示了系统的一种合法状态。图8.1(a)所示的特定链接必定会有不存在的时候,甚至在系统运行的整个时间,都根本不会出现这个特殊的对象结构,但是,它的确表示了可能出现的情形,如果现实世界的实际情况需要这种情形。图8.1(b)的情况则不同。一门课程选修另一门课程是没有意义的,因此在大学档案系统的例子中这个图是完全没有意义的。我们不能问它描述的情形是真或是假,因为它根本不能描述一种有意义的情景。然而,不可能通过明确地考虑所有可能的对象图,并将它们分为合法或不合法来详细说明系统,因为的确存在着太多的对象图。为了说明任何表示了系统合法状态的对象图都必须具有的性质,需要一种更一般的方法。为此目的,UML使用类图。类图作为一种系统说明书,除了别的方面以外,它规定可以存在什么类型的对象,这些对象封装什么数据,以及系统中的对象如何彼此关联在一起。例如,学生档案系统的一个适当的类图可以清楚地表明,图8.1(a)表示了系统的一种可能状态,而8.1(b)是不可能的。本章描述UML类图的特征,并说明如何用类图指定软件系统某些结构上的特性。本章使用的例子是假想的,只是为了讨论系统的静态结构,而丝毫不涉及该结构应该支持的处理。这种简化在介绍表示法的细节时有好处,但是不能作为如何使用和开发类图的实际可行的说明。如第5章的例子所指出的,类图的开发通常与交互图密切相关,交互图有助于标识系统中所需要的类。8.1数据类型和众多程序设计语言一样,UML也定义了许多基本数据类型,而且也提供了用以定义新类型的机制。数据类型代表简单的、无结构的数据种类,例如数值、字符和布尔值。数据类型一般用于指定类中的属性的类型和操作参数的类型。数据类型的实例称为数据值。数据值不同于对象,数据值没有本体的概念。例如,整数2的两个不同当前值,存储在不同的位置,会认为是相同的数据值,并且在检测是否相等时会返回“true”。但是,两个对象总认为是不同的,即使它们的状态相同。UML中可以使用的数据类型分为三类。首先,有许多预定义类型,主要有整数、字符串和布尔值。UML定义这些类型的表示法如图8.2所示,尽管实际上只是在类型表达式中使用其名字。UML中没有定义这些类型的值,但假定是不言自明的。图8.2UML中的预定义数据类型数据值是没有结构的,所以数据类型不定义属性或操作。然而,可以为数据类型定义纯函数:它们返回数据值,但是不能修改它们的参数。数据类型还可以定义为枚举,实质上和许多编程语言提供的枚举类型相同。枚举的值是一组命名的枚举字面值。布尔值用一个预定义的枚举表示,如图8.2所示。该类型的字面值是true和false两个值。用户定义的枚举可以通过将枚举字面值列举在图标下部的栏中定义,如图8.3所示。图8.3用户定义的枚举最后,模型可以使用编程语言数据类型。这就允许特定编程语言的类型可以在UML中使用。这在从代码逆向构造一个类的时侯,或者在实现一个设计时,例如可能必须指定使用指针或数组类型,就很有用。重数在UML中,有许多地方必须声明给定实体在某些情况下可以出现多少次。这用重数表示。重数是一个整数集合,该集合的每个成员代表指定实体可能出现的数量。在UML中重数作为数据类型来定义,用重数范围表示。范围由用圆点隔开的一对整数表示,例如0..9。特殊符号*的意思是“无限制的”,可以用于表示没有上界的范围。因此,0..100表示从0到100的所有整数,包括0和100,而0..*表示所有的非负整数。两端数字相同的重数范围,如1..1,用单个的数字1表示。通常,重数由包含数字范围和单独数字的列表给定,最好以升序排列。例如,假定一个给定实体是可选的,但如果出现,则至少必须是三个。这个重数可以表示为0,3..*。8.2类简化描述无限数量的对象的基本技术是将相似的对象分组。共享某些特性和行为的对象放在一个组中,并为每个组定义一个类。类不描述个体的特殊性质,而是指定组中所有对象共享的公共特征。例如,图8.1显示了代表假想的大学档案系统中的学生和课程的对象。在这样一个系统中,将会为每个学生存储相同的一些信息,如姓名和地址,而对各个学生实际存储的数据值则不同。通过定义一个学生类,我们可以一次性地规定系统将存储的关于学生的信息的结构。这同样适用于操作:例如,修改地址的操作,潜在地适用于任何学生,或者换句话说,每个学生对象必须将此作为自己的操作提供。通过将操作描述为学生类的一部分,我们说明了它对所有学生对象的适用性。在UML中,用一个矩形框来图形化地表示一个类。类的名字用粗体写在矩形框的上部。接下来的几节将描述表示类的对象的特性的方法。然而,在许多情况下,只将类的名字包含在图标中就已足够。各个对象,其结构是通过一个类描述,称为该类的实例。另外,也可以说这些对象“属于一个类”。每个对象都是某个类的实例,这是对象定义的不可缺少的部分,并决定了该对象中将存储什么数据。为了强调类和实例之间的关系,UML用和类相同的图标表示对象。在类名前加冒号,并加下划线,而且实例也可以命名。图8.4显示了一个“Student”类,以及它的两个实例。图中的虚线称为依赖性,是UML用来表示两个模型元素之间未指定种类的关系的表示法。依赖性上所附的标注,或构造型,指出描述的是什么特殊关系。图8.4中,“instanceOf”依赖表明对象是指定类的实例。图8.4类及其实例然而,对象是指定类的实例的事实已经通过在每个对象的标注中使用该类的名字表达了,所以图8.4所示的表示法很少使用。实际上,类和对象图标在正常情况下是不会一起出现在同一个图中的。类重数重数的概念可以应用于类:类的重数规定了在任一给定时间可以存在的该类的实例数。类的缺省重数是“零或多个”,意指可以创建的实例数目没有限制。缺省重数不需要在图中表示出来。但是,在有些情况下,想要对系统运行时任何给定时间能够存在的实例数目指定某些限制。为了做到这点,类可以包含一个重数注文,放在类图标中的右上角。这种表示法最常见的使用是说明一个类是单实例类,即只能有一个实例。例如,学生档案系统可能需要记录大学本身的某些信息,因而要定义一个类保存这些信息。但是,因为系统完全是在一所大学内部,所以这个类有多个实例是没有意义的。这个约束用图8.5所示的类符号表示。图8.5一个显示类重数的单实例类8.3用类描述对象每个对象都包含某些数据以及若干处理这些数据的操作。给定类的所有对象包含相同的数据项和相同的操作,虽然数据项具有不同的实际值。这种公共结构通过对象所属类中的若干特征定义,包括属性和操作,属性描述的是类的实例中的数据项。8.3.1属性属性是对类的每个实例所维护的数据域的描述。属性必须命名。除了名字,还可以提供其他信息,例如属性描述的数据的类型,或者属性的缺省初值。属性在类图标中类名下面的另一栏中显示。如果显示了属性类型,类型和名字之间用冒号隔开,后面写等号和初值。但是,在设计的早期阶段,最常见的是只显示属性的名字。图8.6的例子说明了类的属性的表示法。图8.6属性和属性值图8.6显示了表示课程的一个类,它具有课程的编号、名字和学分建模的属性。图中还显示了该类的一个实例,以说明在对象图标中指定属性值的方式。第一个属性名为“code”,表示该大学内用以引用该课程的标识符,这个属性没有指定类型,表示还没有决定如何将此代码存储为具体的数据。数据类型可以用于表示属性的类型,而类通常却不用作属性的类型。例如,如果一个模型中定义了表示学生和课程的类,那么将学生选修的课程作为学生类中的一个属性,其类型为“module”,这似乎很有吸引力。对这种情况建模更好的方法是使用学生类和课程类之间的一个关联,如8.4节描述的。图8.6中显示的属性具有实例作用域,意思是类的每个实例可以存储该属性的一个不同值。然而,有些数据描述的不是个别实例,而是所有当前实例的集合。例如,我们可能想记录系统所知的课程的总数,一种方法如图8.7所示。图8.7具有类作用域的属性加下划线的属性,例如图8.7中的“mcount”,称为具有类作用域。这意味着该属性只有单独一份,可以由该类的所有实例访问。具有类作用域的属性对应于编程语言中的静态变量或类变量。属性也可以有明确定义的重数。属性的缺省重数是“正好一个”,暗指类的每个实例正好保存每个属性的一个值。但是,在有些情况下,这个缺省值并不合适。假定扩充课程类,包含一个课程结束时记录考试日期的属性。因为有些课程可能没有这样的考试,类的一些实例不需要保存数据值,在此意义上这个属性就是可选的。这可以通过在属性名字后面增加重数说明来表示,如图8.8所示。图8.8属性重数图8.8中还出现了一个属性staff,其重数是“多个”,其目的是保存讲授该课程的教员的姓名。具有大于1的重数的属性在许多方面等价于一个数组,这也可以直接通过使用适当的语言类型指定。8.3.2操作和属性一样,操作也可以显示在类图标中。这些是类的每个实例都提供的操作,例如,课程类可能提供了设置和检索课程名称以及学生报名选修该课程的操作。操作显示在类图标底部的另一栏中,如图8.9所示。在类图标中,属性和操作栏可以都省略,或省略二者之一,并且空栏不必在图标中显示。图8.9带有属性和操作的课程类操作具有名字,还可以有参数和返回结果,如同编程语言中的函数一样。操作的参数和返回类型可以是数据类型的名字,像指定属性类型所使用的那样,或者是类的名字。和属性一样,除了操作名字之外,其他的所有信息都是可选的。根据开发过程到达的阶段,可以提供适当的或多或少的信息。在类图中省略操作很常见。原因是在孤立地考虑一个类时,很难决定该类应该提供什么操作。必要的操作是通过考虑系统的全局行为是如何由组成系统的对象网络实现而发现的。这种分析是在构造系统的动态模型时进行的,并且只有接近设计过程结束时才可能搜集到一个类的操作的完整定义。图8.9中的操作具有实例作用域,意思是它们将应用于该类的各个实例上,而且只能在已经创建了实例时调用。也可以定义具有类作用域的操作;这些操作可以独立地被该类的任何实例调用,但作为结果它们只能访问也具有类作用域的属性。图8.10显示了一个操作,返回当前存在的课程类的实例数目。图8.10具有类作用域的操作在UML中,构造函数,即创建类的新实例的操作,也具有类作用域,尽管它们有些和其他操作稍微不同的特性。图8.10显示了一个构造函数,遵循一般惯例,构造函数和类具有相同的名字。8.3.3标识对象在第2章,对象本体的概念是作为对象模型的一个本质部分引入的。对象本体是对象一个无须明确表示的隐含性质,它使得该对象能够和系统中的其他所有对象区分开来。在面向对象程序设计语言中,对象在内存中的地址不能由任何其他对象共享,通常被用作对象本体的实现。对象本体不用UML的数据类型表示,因此不能在模型中明确给出。特别地,对象的本体和对象的任何属性截然不同。很可能两个不同对象的所有属性的值都相同,如图8.11所示,但仍然是不同的对象,可以由它们的不同本体区分。图8.11具有相同状态的不同对象在模型中,对象本体文字上可以用在该对象的类
本文标题:第8章类图和对象图
链接地址:https://www.777doc.com/doc-2199309 .html