1、第7章 面向对象设计4学时引言面向对象的设计物理结构设计物理结构设计子系统层次设计子系统层次设计用例设计用例设计类设计类设计数据库设计数据库设计界面设计界面设计设计模型设计模型设计规范设计规范/模版模版按照规范把分析模按照规范把分析模型转化为设计模型型转化为设计模型第7章 面向对象设计1)面向对象设计方法和步骤2)面向对象设计的概念3)面向对象设计规格说明书的主要内容理解了解了解要求要求7.1 面向对象设计的概念o 面向对象设计强调定义软件对象,并且使这些软件对象相互协作来满足用户需求。o 面向对象分析和设计的界限是模糊的,从面向对象分析到面向对象设计是一个逐渐扩充模型的过程。分析的结果通过细
2、化直接生成设计结果,在设计过程中逐步加深对需求的理解,从而进一步完善需求分析的结果。o 分析和设计活动是一个反复迭代的过程。o 面向对象方法学在概念和表示方法上的一致性,保证了各个开发阶段之间的平滑性。o 面向对象设计的四个层次:n 确定系统的总体结构和风格,构造系统的物理模型,将系统划分成不同的子系统。n 中层设计:对每个用例进行设计,规划实现用例功能的关键类,确定类之间的关系。n 进行底层设计:对每个类进行详细设计,设计类的属性和操作,优化类之间的关系。n 补充实现非功能性需求所需要的类。o 面向对象设计与结构化设计的过程和方法完全不同,要设计出高质量的软件系统,记住:n 对接口进行设计n
3、 发现变化并且封装它n 先考虑聚合然后考虑继承强内聚o 类内聚设计类的原则是一个类的属性和操作全部都是完成某个任务所必须的,其中不包括无用的属性和操作。n 例如设计一个平衡二叉树类,该类的目的就是要解决平衡二叉树的访问,其中所有的属性和操作都与解决这个问题相关,其他无关的属性和操作在这里都是垃圾,应该清除。弱耦合o 在面向对象设计中,耦合主要指不同对象之间相互关联的程度。如果一个对象过多地依赖于其它对象来完成自己的工作,则不仅使该对象的可理解性下降,而且还会增加测试、修改的难度,同时降低了类的可重用性和可移植性。o 对象不可能是完全孤立的,当两个对象必须相互联系时,应该通过类的公共接口实现耦合
4、,不应该依赖于类的具体实现细节。耦合(续)o 交互耦合如果对象之间的耦合是通过消息连接来实现的,则这种耦合就是交互耦合。在设计时应该尽量减少对象之间发送的消息数和消息中的参数个数,降低消息连接的复杂程度。耦合(续)o 继承耦合继承耦合是一般化类与特殊化类之间的一种关联形式,设计时应该适当使用这种耦合。在设计时要特别认真分析一般化类与特殊化类之间继承关系,如果抽象层次不合理,可能会造成对特殊化类的修改影响到一般化类,使得系统的稳定性降低。另外,在设计时特殊化类应该尽可能多地继承和使用一般化类的属性和服务,充分利用继承的优势。可重用性o 软件重用是从设计阶段开始的,所有的设计工作都是为了使系统完成
5、预期的任务,为了提高工作效率、减少错误、降低成本,就要充分考虑软件元素的重用性。重用性有两个方面的含义:n尽量使用已有的类,包括开发环境提供的类库和已有的相似的类;n如果确实需要创建新类,则在设计这些新类时考虑将来的可重用性。o 设计一个可重用的软件比设计一个普通软件的代价要高,但是随着这些软件被重用次数的增加,分摊到它的设计和实现成本就会降低。框架o 框架是一组可用于不同应用的类的集合。框架中的类通常是一些抽象类并且相互有联系,可以通过继承的方式使用这些类。例如,Java应用程序接口(API)就是一个成功的框架包,为众多的应用提供服务,但一个应用程序通常只需要其中的部分服务,可以采用继承或聚
6、合的方式将应用包与框架包关联在一起来获得需要的服务。一般不会直接去修改框架的类,而是通过继承或聚合为应用创建合适的GUI类。面向对象设计的活动o 系统构架设计o 用例设计o 类设计o 数据库设计o 用户界面设计。7.2 构架设计o 构架设计的目的是要勾画出系统的总体结构,这项工作由经验丰富的构架设计师主持完成。o 该活动以用例模型、分析模型为输入。o 输出:物理结构、子系统及其接口、概要的设计类。o 第1步:构造系统的物理模型o 首先用UML的配置图描述系统的物理构架o 将需求分析阶段捕获的系统功能分配到这些物理节点上。o 配置图上可以显示计算节点的拓扑结构、硬件设备配置、通信路径、各个节点上
7、运行的系统软件配置、应用软件配置。o 一个图书馆信息管理系统的物理模型如图示 o 配置图中n 考虑到图书馆内部用户如果也通过互联网使用系统,效率会受影响。n 这个系统中设计了三种访问模式:一种是远程读者,通过Internet访问系统,实现查询图书、预借图书的功能;第二种是本单位其他部门的读者,通过单位局域网查询、预借图书;第三种是图书馆内部工作人员,在局域网上完成日常的借还书、采编、图书管理等工作。第2步 设计子系统o 对于一个复杂的软件系统来说,将其分解成若干个子系统,子系统内还可以继续划分子系统或包,这种自顶向下、逐步细化的组织结构非常符合人类分析问题的思路。o 每个子系统与其它子系统之间
8、应该定义接口,在接口上说明交互信息,注意这时还不要描述子系统的内部实现。1)划分各个子系统的方式:按照功能划分,将相似的功能组织在一个子系统中;按照系统的物理布局划分,将在同一个物理区域内的软件组织为一个子系统;按照软件层次划分子系统,软件层次通常可划分为用户界面层、专用软件层、通用软件层、中间层和数据层,具体的表达方式见图。o 用户界面层是与用户应用有密切关系的内容,主要接受用户的输入信息,并且将系统的处理结果显示给用户。这部分变化通常比较大,所以建议将界面层剥离出来,用一些快捷有效的工具实现。o 专用软件层是每个项目中特殊的应用部分,它们被复用的可能性很小。在开发时可以适当地减小软件元素的
9、粒度,以便分离出更多的可复用构件,减少专用软件层的规模。o 通用软件层是由一些公共构件组成,这类软构件的可复用性很好。在设计应用软件时首先要将软件的特殊部分和通用部分分离,根据通用部分的功能检查现有的构件库。如果有可用的构件,则复用已有的构件会极大地提高软件的开发效率和质量。如果没有可复用的构件,则尽可能设计可复用的构件并且添加到构件库中,以备今后复用。o 数据层主要存放应用系统的数据,通常由数据库管理系统管理,常用的操作有更新、保存、删除、检索等。在图书馆图书信息管理系统层次划分:o 系统层采用微软的Windows操作系统和SQL Server数据库。o 数据层主要是建立应用数据库,包括数据
10、库表、视图等。o 中间层使用微软的ADO.NET,实现对数据库的插入、修改、删除的事务处理。o 通用软件层实现权限管理、用户登录、通用查询类。o 专用软件层实现读者查询、借书、还书、处罚、预订、通知等处理。o 界面层实现查询界面、借书界面、还书界面、预订界面、通知界面等用户界面。2)定义子系统之间的关系:o 划分子系统后,要确定子系统之间的关系。子系统之间的关系:n“请求服务”关系,“请求”子系统调用“服务”子系统,“服务”子系统完成一些服务,并且将结果返回给“请求”子系统。n平等关系,每个子系统都可以调用其它子系统。n如果子系统的内容相互有关联,就应该定义它们之间的依赖关系。在设计时,相关的
11、子系统之间应该定义接口,依赖关系应该指向接口而不要指向子系统的内容。注意:o 如果两个子系统之间的关系过于密切,则说明一个子系统的变化会导致另一个子系统变化,这种子系统理解和维护都会比较困难。o 解决子系统之间关系过于密切的办法基本上有两个:n 重新划分子系统,这种方法比较简单,将子系统的粒度减少,或者重新规划子系统的内容,将相互依赖的元素划归到同一个子系统之中;n 定义子系统的接口,将依赖关系定义到接口上;3)定义子系统的接口。每个子系统的接口上定义了若干操作,体现了子系统的功能,而功能的具体实现方法应该是隐藏的,其他子系统只能通过接口间接地享受这个子系统提供的服务,不能直接操作它。第3步
12、非功能需求设计o 分析阶段定义了整个系统的非功能需求,在设计阶段要研究这些需求,设计出可行的方案。非功能需求包括:n 系统的安全性,错误监测和故障恢复,可移植性和通用性等等。o 具有共性的非功能需求一般设计在中间层和通用应用层,目的是充分利用已有构件,减少重新开发的工作量。7.3 进一步细化用例o 根据分析阶段产生的高层类图和交互图,由用例设计师研究已有的类,将它们分配到相应的用例中。o 检查每个用例功能,依靠当前的类能否实现,同时检查每个用例的特殊需求是否有合适的类来实现。o 细化每个用例的类图,描述实现用例的类及其类之间的相互关系,其中的通用类和关键类可用粗线框区分,这些类将作为项目经理检
13、查项目时的重点。o 第1步:通过扫描用例中所有的交互图识别参与用例解决方案的类。在设计阶段完善类、属性和方法。例如,每个用例至少应该有一个控制类,它通常没有属性而只有方法,它本身不完成什么具体的功能,只是起协调和控制作用。o 每个类的方法都可以通过分析交互图得到,一般地检查所有的交互图发送给某个类的所有消息,这表明了该类必须定义的方法。例如“借书控制”类向“读者”类发送“检查读者(读者编号)”消息,那么“检查读者”就作为“读者”类应该提供的方法。o 第2步:添加属性的类型、方法的参数类型和方法的返回类型。o 第3步:添加类之间的关系,包括关联、依赖、继承。o“借书”用例中的各个类的关系图,因为
14、类有三种类型即界面类、控制类和实体类,为了清晰起见,我们用粗线框表示控制类,斜体字表示界面类,正常的表示实体类。7.4 详细设计一个类o 由构件工程师详细设计每个类的属性、方法和关系。第第1 1步:定义类的属性步:定义类的属性o 用所选择的编程语言定义每个类的属性。类的属性反映类的特性,通常属性是被封装在类的内部,不允许外部对象访问 类属性设计的注意点:o分析阶段和概要设计阶段定义的一个类属性在详细设计时可能要被分解为多个,减小属性的表示粒度有利于实现和重用。但是一个类的属性如果太多,则应该检查一下,看能否分离出一个新的类。o如果一个类因为其属性的原因变得复杂而难于理解,那么就将一些属性分离出
15、来形成一个新的类。o通常不同的编程语言提供的数据类型有很大差别,确定类的属性时要用编程语言来约束可用的属性类型。定义属性类型时尽可能使用已有的类型,太多的自定义类型会降低系统的可维护性和可理解性等性能指标。o类的属性结构要坚持简单的原则,尽可能不使用复杂的数据结构。o 设计类的属性时必须要定义的内容:n 属性的类型:设计属性时必须要根据开发语言确定每个属性的数据类型,如果数据类型不够,设计人员可以利用已有的数据类型定义新的数据类型。n 属性的可见性。在设计属性时要确定公有属性、私有属性、受保护属性。o 设计类的属性时主要的选择内容:n属性的初始值:如果默认值,用户在操作时会感觉很方便。例如在计
16、算税费的程序中,如果定义了初始默认税率,用户就不必每次都重复输入税率值。n属性在类中的存放方式:By value(按数值)属性放在类中。By reference(引用)属性放在类外,类指向这个属性。后面这种情况一般是属性本身为一个对象,例如“教研室”类有一个属性是“教师”,而“教师”对象本身在“教研室”类之外已经定义了,这时“教研室”类中只保存一个指针指向这个外部对象。第2步:定义类的操作o 由构件工程师为每个类的方法设计必须实现的操作,并用自然语言或伪代码描述操作的实现算法。一个类可能被应用在多个用例中,由于它在不同用例中担当的角色不同,所以设计时要求详细周到。设计类操作的注意事项:o 分析
17、类的每个职责的具体含义,从中找出类应该具备的操作。o 阅读类的非功能需求说明,添加一些必须的操作。o 确定类的接口应该提供的操作。这关系到设计的质量,特别是系统的稳定性,所以确定类接口操作要特别小心。o 逐个检查类在每个用例实现中是否合适,补充一些必须的操作。o 设计时不仅要考虑到系统正常运行的情况,还要考虑一些特殊情况。o 例如,一个对象结束前必须释放占用的资源,在并发系统中,一个任务结束前必须通知其它任务自己已经结束;出错是不可预见的系统终止,可能是应用错误、系统资源短缺或外部中断引起的。o 经验丰富的设计者可以预见有规律的出错,但是不论多么完善的设计都不能保证系统中没有错误。好的设计通常
18、在可能出现致命错误的地方设计一个良好的出口,在系统终止前尽可能清晰地保留当时的信息和环境,尽可能多的反应出错误信息。设计类的操作时必须要定义的内容:o 操作描述:说明操作的具体实现内容,可以用伪代码或者文字描述操作的处理逻辑。o 定义操作的参数:说明每个参数名称和类型。o 操作返回类型:可以是编程语言的内置数据类型,也可以是设计人员自定义的数据类型。o 操作可见性:Public、Private和Protected。在UML中用+、-、#符号表示。o 操作异常:说明每个操作中的异常处理。o 说明操作运行之前要满足的条件和操作运行之后要满足的条件。设计类的操作时主要的选择内容:o 操作的版型:Im
19、plementer型实现业务逻辑功能。Manager型是实现构造器、析构器以及内存管理等管理性操作。Access型访问属性的操作,例如get或set。Helper型是完成自身任务的一些辅助操作。o 第3步定义类之间个关系n 设置基数:一个类的实例与另一个类的实例之间的联系。在图书馆信息管理系统中,“图书”类和“读者”类关联,如果需求说明中有“一位读者可借图书的数量为0至10本”,那么它们之间的基数为1:0.10。n 使用关联类:可以放置与关联相关的属性。例如“图书”类和“读者”类,如果要反映读者的借书情况,该如何处理呢?可以创建一个关联类,这个类中的属性是“借书日期”。o 设置限定:为了减小关
20、联的范围。例如一个目录下虽有多个文件,但是在一个目录范围内确定惟一一个文件,用“文件名”限定目录与文件之间的关系。目录文件文件名7.5 图书馆图书信息管理系统的设计7.5.1 图书馆图书信息管理系统的物理结构说明:节点说明:oWeb服务器:HP ProLiant DL380G3 2.8GHz CPU,1GB内存,73GB*2硬盘;操作系统:Windows 2000;Web服务器软件:MS IIS;Web接口软件:ASP。o应用服务器和数据库服务器:Sun Fire V480,900 MHz CPU,4GB内存,36G*2硬盘;操作系统:Solaris 8 2/02;数据库:MS SQL Ser
21、ver 2000;事务处理:Microsoft Transaction Server。o客户端:奔腾IV 2.0GHz CPU,512内存,80G硬盘;操作系统:Windows 2000;浏览器:IE5.0。o交换机,路由器:略。o 节点间的连接:TCP/IP协议。o 节点的性能设计:有容错处理;数据库每月进行增量备份;图书馆工作人员具有操作权限管理和角色分配。一般读者进行用户名和口令登录检查。7.5.2 设计子系统o划分四个子系统:界面层、专用软件层、通用软件层和数据层。通用软件层包括权限管理、用户登录、通用查询类。专用软件层包括读者查询、借书、还书、处罚、预借、通知等处理。界面层包括实现查
22、询界面、借书界面、还书界面、预借界面、通知界面等用户界面。数据层包括实体类及其相应的服务。o界面层子系统与专用软件层和通用软件层之间是“请求服务”关系,它不可以直接与数据层发生关系。o专用层与通用层有依赖关系和继承关系。o专用层、通用层与数据层之间是“请求服务”关系。7.5.3 设计类图借书类图说明o 借书时,图书管理员打开借书窗口,这个窗口包含了三个对象:读者编号输入栏、图书编号输入栏和确认按钮。当单击了确认按钮后,由控制类分配任务,首先检查读者编号是否存在,读者借书量是否超出限制,如果不存在该读者编号,则显示“读者无效”,如果借阅量已超标,也显示“读者无效”。接着检查图书的有效性。如果图书
23、已经被借出,则提示“图书已被借出”,同时预订图书按钮变为可操作,可以为该读者预订此书。如果检查读者和图书都有效,则进行借书处理,修改相应的图书记录,创建一条借书记录。o 借书用例中的界面类包括:n 借书窗口n 读者无效对话框n 图书无效对话框o 借书用例中的控制类包括:n 借书处理n 检查读者n 检查图书n 借书n 预订图书o 借书用例中的实体类包括:n 读者n 图书n 借还书记录n 预订记录n 借书规则 借书窗口借书处理检查读者检查图书借书读者号图书号单击确认检查读者检查图书借书借书确认顺序图说明o 其中的借书处理、读者确认、图书确认和借书都是控制类。每个控制类还可以分别画出子顺序图,例如,
24、检查读者是一个控制类,它不实现具体的功能,只是负责协调其他各个类的协作,可以进一部细化顺序图如下:图书已被借空要求预订的顺序图 设计界面类设计实体类读者类:映射到数据库的T-READER表上职责:保存读者信息。属性:项目 类型 长度 备注 读者编号(PK)CHAR 10 读者姓名 CHAR 10部门 CHAR 50 E-MAIL CHAR 20职称 CHAR 10操作:保存(SAVE)删除(DELETE)读取(READ)插入(INSERT)创建(CREAT)关系:与借还书记录相关,它的主键是借还书记录的外键之一。o 检查读者类:检查读者的有效性n 无效编号=0。n 接收借书界面类传递来的读者编
25、号和图书编号。n 检索数据库的T-READDER表,如果不存在该读者编号,则无效编号=1(读者无效)。n 检索T-LOAN表和借书规则表,如果借数量超过限制,则无效编号=2(超出借阅量)。n 如果返回值大于0,则向读者无效窗口类发送消息“显示(无效编号)”。本章要点o面向对象设计的三句经典名言对接口进行设计发现变化并且封装它先考虑组合然后考虑继承。o面向对象设计中的主要内聚有:服务内聚和类内聚。耦合两类:交互耦合和继承耦合。o面向对象的设计活动主要有:系统构架设计、用例设计、类设计、数据库设计和用户界面设计。o构架设计是以分析模型为输入,生成系统的物理构架、逻辑构架(子系统)及其接口、概要的设计类。o根据分析阶段产生的高层类图和交互图,细化每个用例的类图,描述实现用例的类及其类之间的相互关系。o详细设计每个类的属性、方法和关系。