第4章 类图实战.doc_第1页
第4章 类图实战.doc_第2页
第4章 类图实战.doc_第3页
第4章 类图实战.doc_第4页
第4章 类图实战.doc_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章类图实战4.1从分析到设计首先,我们先来简单归纳一下在分析阶段生成的文件,如下:1. 类图。类图描述系统内部的静态结构,以领域概念为参考对象。如果应用BCE 模式的话,原先的类图会是实体类图,而在序列图生成后,会额外生成边界类图和控制类图。2. 用例图。用例图描述系统的外部行为,也就是描述参与者如何与系统交互,以便获取服务的使用过程。3. 序列图。序列图描述系统的内部行为,针对每一个用例,至少会有一张描述主要流程的序列图。在应用BCE 模式之后,序列图内部的一群对象,将由边界对象、控制对象和实体对象所组成。换言之,序列图的一群对象必须来自于类图,而对象之间的交互过程,则来自于用例描述。分析阶段与设计阶段最大的差别在于,分析阶段所关注的重点在领域概念、业务流程等,并未考虑并涉及实际工作平台。所以,到了设计阶段,不再需要花费太多时间在业务概念上 ,取而代之的是,必须把精力放在实际工作平台上,承接分析阶段的类图、用例图、序列图再加上实际工作平台或者是开发人员的观点,生成可以交付给程序员的设计文件。因此,在本书的开发流程规划中,我们会让设计师直接承接分析师的生成文件,进行下述的加工:1. 类图。分析师所生成的类图通常跟实际工作平台有些差别,所以设计师要补上一些实际工作平台的概念,让设计出来的类图可以真正交付给程序员实际工作。2. 用例图。之前我们没有教给分析师用例之间的包含关系和扩展关系如何处理,只是让用例图保持单纯化,以便将焦点聚焦在业务流程上。此处,我们会教设计师如何加入开发人员的观点,使用包含关系和扩展关系,罗列出可以共享的部分,并且让用例图更为细致化。3. 序列图。在分析阶段的序列图并没有太重视消息上的参数,在设计阶段,每张序列图都要拿出来再检查一次,加上所需要的参数。由于,有些分析师已经太久没摸过程序代码了,所以生成的序列图偏离实际工作情况太大,需要设计师来补上这一块,否则程序员是很难直接参考分析文件编写程序代码。好了,接下来,我们要再来多谈一些类图中的元素,这些元素可能对分析师意义不大,但是对设计师而言,会是非常实用的概念。4.2设计师必学元素4.2.1依赖关系之前,我们学到了类之间的关联或组合关系,它们都是一种需要长期保存在数据库中的静态关系。相较之下,“依赖关系(dependency relationship)”是一种暂时的、动态的关系,它不需要被长期保存,可以在使用的瞬间建立,如果不用了就回收。因此,当两个对象之间可以互传消息时,意味着两个对象之间存在需要长期保管的静态关系,或者是暂时性的动态关系。例如,在图4-1 中,边界对象与实体对象之间可以通过动态的依赖关系交互,用完就丢,不需要将这个动态关系保存在数据库中。而房型和景观图片两者之间由于存在组合关系,所以它们可以通过静态关系交互。所以,回过头来看,我们可以在类图中,同时绘制出动态的依赖关系,以及静态的关联或组合关系,如图4-2 所示。依赖关系的图标是带箭头虚线,由扮演依赖角色的“客户端(client)”指向扮演被依赖角色的“支持端(supplier)”。需要特别注意到,既然说是“依赖”则意味着连动性,支持端只要一变动,很可能客户端会受到连动。所以,在建构依赖关系时,被依赖的支持端愈稳定愈好,像是在BCE 模式的概念中,您会发现边界对象、控制对象比较不稳定,所以我们不让稳定的实体对象依赖它们,避免因此而导致整个结构的不稳定。总之,如果两对象之间已经存在静态关系时,可以优先使用静态关系交互,而且记得要将静态关系保存在数据库中。如果两个对象之间没有静态关系,也可以建立暂时性的依赖关系,以便进行交互,而且用完即丢,不需要费心保存在数据库中。4.2.2泛化关系泛化关系(generalization relationship)是一种分类关系;针对同一种概念的事物,区分成一般性的(general)和特定性的(specific),然后再构建起两类之间的一般性关系。例如,在订房系统中,我们可以将景观图片分为两大类:酒店图片和房型图片。相较于原先的景观图片,酒店图片和房型图片两者都属于较为特定的图片,因此我们可以通过泛化关系构建出三者的关系,如图4-3 所示。实际工作中, 我们常称一般端的类为“父类(superclass)”, 特定端的类为“子类(subclass)”。而且,在泛化的图标上,也可以多个子类共享大三角形端点,如图4-4 所示。在泛化关系中,有个很重要的特色是,子对象可以替代父对象;这是因为子类继承了父类的特征,具体来说,子类可以通过泛化关系继承父类的属性、操作与静态关系。还记得,前面我们说过静态关系是指关联,而组合关系则是关联的一种。所以,请看图4-5 的例子,虽然酒店图片和房型图片并未定义任何属性、操作和关系,但其实它们已经拥有景观图片已经定义好的属性、操作和关系了,这就好比小孩继承了父母留下来的财产一样。不过,在图4-5 的例子中,如果我们不想继承关系,可以改成图4-6 的设计,特别注意原来图4-5 中0.1 的多重性,到了图4-6 中则改成了1,这样才是正确的多重性。再者,继承而来的属性、操作和关系,也可以在子类处“重新定义(redefine)”,不一定要全盘接受。例如,在景观图片中的“场所”属性并没有默认值,继承之后,我们在它的子类处加上了默认值,重新定义了场所,如图4-7 所示。当然,子类除了继承父类外,也可以额外增加属于自己专用的属性、操作或关系。假设,在房型图片类中,我们需要多记录一项图片的尺寸,但是在酒店图片类中不需要这项属性,如图4-8 所示。4.2.3保护等级虽然,通过泛化关系,子类可以继承父类已经定义好的属性、操作和关系。不过,要是父类将这些成员定义成私有等级(private)的话,子类虽然还是可以继承,但是却无法在子类中直接访问私有成员,使用上颇为不便。特别是属性,一般为了封装性,都会建议设置成私有等级可见性。在这种情况下,UML 设置了另一种“保护等级(protected)”的可见性,能见程度介于私有等级与公有等级之间,专门配合泛化关系使用。在使用上,父类可以将私有等级的成员改成保护等级,这样一来,子类便能够直接访问保护等级的成员。如图4-9 所示,保护等级的符号是“井字”号(#)。4.2.4抽象类在泛化架构中,有时候,父类本身并不完整,所以无法生成对象,这种无法产子的类称为“抽象类(abstract class)”。抽象类同样使用矩形图标,只不过它的类名称采用斜体字,如图4-10 所示。通常,我们之所以会将类设置成抽象类,主要是因为类中含有不具备实际工作内容或者不完整的“抽象操作(abstract operation)”,所以才会将它设置成抽象类。如图4-11 所示,抽象操作的表示法如同一般的操作,只不过操作名称使用斜体字,就跟抽象类的表示法相似。一旦抽象类配合泛化关系后,子类可以针对抽象操作提供完整的实际操作,这样一来,不仅有子对象可用,也可以由子对象来替代父对象,如图4-12 中,酒店图片和房型图片都提供了具体的“查看景观图片”操作。4.2.5类层级之前,我们所看到的属性和操作都属于“对象层级(object-scoped, instance-scoped)”,代表该类所生成的每一个对象都拥有一份对象层级的属性,而且外界也只能通过对象调用对象层级的操作。相对的,有另一种称为“类层级(class-scoped, classifier-scoped)”的属性与操作,代表整个类共享一份属性,而且外界只要通过类就可以调用操作,不需要先生成对象。例如,在订房系统中,会员类内部的“验证”操作,要是设置为类层级的操作,或许会比设置为对象层级的操作,更为恰当。因为,当我们请会员进行验证时,其实根本就还没有正确找出某一个会员对象,所以可能不是请某一个会员对象来进行验证,而是应该找会员类先进行验证,通过验证之后,再找出正确的会员对象才对。所以,如图4-13 所示,类层级的属性与操作名称有下划线,之前我们看到没有下划线的属性或操作都属于对象层级的。还有,由所有会员对象共同维护一份会员总数量即可,所以这个属性也适合设置成类层级的属性。另外,其他像生成对象、删除对象的操作,其实都适合设置成类层级,因为在对象生成之前,该对象根本不存在,怎么能请这个对象执行生成自己的动作呢?至于删除对象也应该同样交给所属类来执行,或许会比请对象自动释放,要合适得多。4.2.6公有类抽象类因为不完整,所以不能生成对象,而“公有类(utility class)”则是因为它所拥有的属性、操作都是“类层级”的,所以我们不需要生成对象,就可以直接使用公有类所提供的属性和操作。顾名思义,公有类存在的目的,就是像工具一样,让所有类、对象使用的。虽然,公有类不生成对象,但是它是完整的,跟抽象类不同。所以,公有类的图标是一般的矩形,名称底下没有下划线,不过类名称上面会标示,用来区分它是个公有类。再者,公有类里所有属性和操作,都必须是类层级的,不能设置对象层级的属性及操作。如图4-14 所示,我们为订房系统设计一个“自动生成序号”的公有类,让其他类、对象都可以使用它来自动产生序号。4.2.7枚举类型前面,我们都在谈类或对象,最后我们来看一个特殊的数据类型(data type)概念,即“枚举类型(enumeration)”。枚举类型也采用矩形图标,不过名称上面多了的字眼,而且除了属性和操作外,矩形内部最底部多了一行放置“枚举值(enumerationliteral)”,如图4-15 所示。图4-15枚举类型不过,由于我们不经常为枚举类型设置属性和操作,所以大部分时候,枚举类型的属性行和操作行都会被隐藏起来,仅出现枚举类型名称和枚举值。如图4-16 所示,我们设计了一个名为“床型种类”的枚举类型,然后把床型的数据类型设为床型种类,限制床型只能是其中的一种枚举值。图4-16 “床型种类”枚举类型4.3从面向对象到关系型数据库在UML 中,系统以对象的方式在运行,当然也包含以对象的方式存储在数据库中。可是,实际工作的中,并不总是如此完美,虽然面向对象数据库(Object-Oriented Database,OODB)已经发展多年,但关系型数据库却是目前的主流技术。所以,从面向对象到关系型数据库,一直是一个鸿沟,却也是许多年来微软等大厂商一直努力投入的主题。所幸,近年来,关于“对象关系映射(Object-Relational Mapping, ORM)”技术有较大的进展,例如,Java 阵营发展出来的Hibernate,或是微软自家发展出来的“实体框架(Entity Framework)”,填补了面向对象与关系型数据库之间的鸿沟。因此,很幸运地,我们可以比过去的前辈们,更专心在面向对象技术中,无须太过担心数据库端的转换。本书假设后端采用关系型数据库,而且我们也不愿意花时间绘制实体关系图(ERD)的情况下,设计师可以选择在类中加入关系型数据库的“主键(Primary Key,PK)”和“外键(foreign key, FK)”的概念,让实体类图可以一图两用,同时落实到程序代码和关系型数据库。特别注意到,在面向对象的程序设计中,对象之间通过连接就可以连接到对方,因此类之间有静态关系,也就不需要额外加入键值,特别是外键的概念。所以,如4-17 所示,每一个类中的属性都是自己的属性,并没有抓别的类的属性过来当外键。但是,在关系型数据库中,数据表中必须设置键值,所以设计师得在类中设置主键,并且增加做为外键的属性。如图4-18 所示,我们可以在属性前面加上 代表主键,并加上 代表外键。原本在订房类中,并没有“电子邮件”这个属性,现在把会员的电子邮件抓过来当外键。同样的,本来在订房明细中也没有“订房序号”,现在也得把订房类中的订房序号抓过来当外键。4.4酒店联合订房系统既然,在分析阶段都已经生成用例了,接下来在设计阶段,设计师还是以用例为工作单元,检验每一个用例中所涉及的BCE 类,为这些类进行加工。重点加工的部分有以下内容:1. 把中文的类名称、属性名称、操作名称都变成英文。如果您在分析阶段就已经采用英文的话,可以先在不确定的英文名称前头加上双斜线(/),在设计阶段确认之后,才把双斜线去掉。特别是操作名称,通常在分析阶段都比较不确定。当然,如果在分析阶段就已经非常确认的话,也可以不加双斜杠,直接就用英文名称。2. 针对每一个用例,建立BCE 类图,并且加上BCE 类之间的依赖关系。3. 针对前面提到的依赖关系、泛化关系、保护等级可见性、抽象类、类层级属性与操作、公有类和枚举类型,都要找一找以修正一下实体类图。4. 针对更新后的实体类图,加上适当的主键和外键。至于操作中的输入参数和返回参数,我们到了设计序列图的时候,才来检验并加工。还有,边界类和控制类,也是稍后再来加工,这里设计师可以先专注重要的实体类图。目前为止,我们已经分析过的用例,一共有:会员登录、查询酒店数据查询房型数据、通知已支付订金、订房,如图4-19 所示,接下来我们就逐个来加工吧!4.4.1用例会员登录在会员登录用例中,主要用到“会员”实体类,如图4-20 所示。除了把会员的类名称、属性、操作全改成英文名称外,还需要将原来“账号状态”属性和“验证”操作的回复参数的数据类型改成枚举类型,如图4-21 所示。至于主键的部分,之前举例时已经加工过了,这里就不再说明了;外键的部分,等出现与其他类之间的静态关系,再来修改。4.4.2用例查询酒店数据“查询酒店数据”用例很简单,连控制对象都没设置,仅做数据库查询的工作,它的BCE 类依赖关系如图4-22 所示。在图4-23 中,有几个重点,如下:1. 在景观图片的部分,我们并没有使用前面谈到的泛化架构,而是让酒店和房型都连到这个景观图片。所以,景观图片的外键会有两个来源,一个是来自酒店,另一个来自房型。因此,另外取了“场所序号(placeNumber)”做为景观图片的外键名称。2. 再者,我们为景观图片的“场所(place)”属性,设计了一个PicturePlace 枚举类型,其枚举值有酒店和房型两个。3. 至于酒店序号也一并通过“自动生成序号(NumberGenerator)”公有类自动生成。4.4.3用例查询房型数据见图4-24 关于“查询房型数据”的BCE 类图,其中的“景观图片(Picture)”实体类前面已经加工过了,所以这里就仅列出实体类的图标,把它的属性和操作隐藏起来了。接着,加工后的如图4-25 所示,几项重点内容介绍如下:1. 房型类中的“计算房价”操作,一直都还没用到,所以我们就先把它删除了,日后有需要再补上。2. 由于订房系统中可能会用到房间(Room) 类, 所以这里的“房型”就翻译成“RoomType”了。3. 还有,房型类已经有“床型(bed)”属性了,所以似乎不再需要用到“种类”属性,所以我们也把这个属性删除了。4. 再者,房型名称是指酒店经营者为房型取的名称,例如,尊贵总统房、紫色浪漫屋之类的房型昵称。5. 自动生成序号(NumberGenerator)公有类增加了一个“产生房型序号(generate-RoomTypeNumber)”的操作,所以我们又将这个类更新了一次。4.4.4用例通知已预订接着,再来看“通知已预订”

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论