第9章面向对象设计本章计划学时:8~10学时本章主要内容•设计体系架构–分层模式–包•设计软件类–设计软件类–软件类的属性和方法–为类添加方法–泛化和关联的设计•对象持久化和数据库•设计原则和设计模式9.1面向对象的设计•面向对象分析和设计基于相同的模型,一般认为没有严格的阶段性和很明显的界限。•面向对象设计阶段还是有明确的目标,具体内容包括:–设计软件体系结构,定义系统的高层划分,确定主要组件及其接口。–详细设计软件类或接口。按照架构模式定义信息系统的边界类、控制类和实体类,详细设计类的属性和方法,设计程序执行的交互图。–设计数据库接口,解决面向对象模型到数据库模型的过渡。9.2设计软件体系结构•分层模式•包•子系统和接口9.2.1层•下层组件负责对上层组件提供服务。•上层组件可以使用下层组件定义的服务,但下层组件对上层组件一无所知。•层与层之间通常是不透明的,每一层都具有独立的职责。•不同层的软件构件可以分布在多台机器上,也可以部署在同一台机器上。1、层的概念•自从C/S出现之后,软件就被分层了:–Client端的软件完成前台任务,Server端的软件完成后台任务(一般是DBServer)–Client使用Server端的服务,依赖于Server端•自从Internet出现之后,软件进一步分层:–Client端的软件(IE浏览器)完成输入输出任务,WebServer上的程序提供业务逻辑处理,后台DBServer完成数据的存取•C/S常被称为传统的两层,B/S称为三层•本书的分层将不包含有关系统软件(如IE、DBMS等),仅讨论应用系统2、分层模式•传统C/S,无明显分层•两层•三层•四层•多层•基本思想:将逻辑功能相似的类封装到一个组件中。–比如都是用于数据库访问的类做成数据库访问组件,所有表达销售领域对象的类做成销售组件。传统的C/S应用程序•界面窗口程序中包含所有的内容,如输入输出、界面逻辑控制、业务逻辑运算等数据库经典的三层结构数据库销售组件支付组件表示层业务逻辑层数据访问层数据库访问组件经典的三层结构1.表现层:处理用户和信息系统之间的交互。•可以是简单的命令行窗口,也可以功能完善的图形用户界面(胖客户端程序),如基于HTML的浏览器界面(瘦客户端程序)。2.业务逻辑层:也称为领域层或应用层,是信息系统所有和领域相关的工作。•如根据输入数据或已有数据进行计算,依赖于数据访问层获取数据或保存数据,类库形式。3.数据访问层:一般指与数据库的交互,主要责任是数据库记录的存取。•如专门的数据访问类简化的层次结构•表现层•业务层+数据访问层甚至简化成没有分层:•窗口程序=表现+业务逻辑+数据存储•程序几乎不能重用扩展的四层结构1.表现层:等同于三层中的表现层。2.控制层/中介层:是表现层和领域层的中介层,也称应用控制器。主要表示业务逻辑中的工作流,一般针对于用例的事件流控制。此外还负责会话状态、数据的合成或分解等事务。3.领域层:业务逻辑中的领域类的集合,不包含复杂工作流。4.数据访问/数据映射层:负责将基于对象的领域层数据映射到数据库关系表中的记录。也称为数据持久层,可自行开发或采用持久化框架。模型视图控制器架构MVC•模型:即相关的数据,它是对象的内在属性•视图:是模型的外在表现形式,一个模型可以对应一个或者多个视图,视图还具有与外界交互的功能•控制器:是模型与视图的联系纽带,控制器提取通过视图传输进来的外部信息转化成相应事件,然后由对应的控制器对模型进行更新;相应的,模型的更新与修改将通过控制器通知视图,保持视图与模型的一致性3、多层的物理配置•由于应用软件封装成不同层次的独立组件,这给软件部署带来了灵活性:–物理一层:所有应用软件的组件都安装配置在一台机器上。比如全部Web程序都在Web服务器上–物理两层:应用软件的组件配置在两台机器上,比如一部分安装在客户端,另一部分配置在应用服务器上–物理多层:客户端、一台或多台应用服务器、数据库服务器,即多台服务器的方式,这是分布式结构的一种形式。4、多层体系结构的动机•客户对数据的访问通过中间层进行了隔离,数据库的安全性提高了•应用程序被分布部署在多个物理节点上,从而增强了处理大量的用户负载或计算任务的能力,系统可靠性和响应速度得到了提高•业务逻辑处于不同的中间服务器,当业务规则变化后,客户端程序基本不做改动,而且某一层的改动不会影响其他层,这也意味着更好的重用和可维护性•将不同层的开发任务在开发者之间适当地分配,有效地利用开发人员的专长和开发技巧,并且能够提高并行开发能力9.2.2包•包(package)是一种逻辑分组手段,可以取UML模型中的任何一种事物,将相关成分聚在一起,以构成更高层的组织单元——包。•最常用的方法是将类以包为单位进行分组,比如上一节提到的层,每一层中的所有类组成一个包。•一个包可以包含其他的包,高层包被分成若干子包,子包又可以在分成更小的包。–但在Java中,包还指代了物理的组织手段如何分包•分包(软件类的分组)有两种原则:–共同封闭原则(CommonClosurePrinciple)。一个包中的各个类应该是由于相似的原则而改变,即将一组职责相似、但以不同方式实现的类归为一个包中。比如按照层来进行分包就是这种类型。–共同复用原则(CommonReusePrinciple)。一个包中的各个类应该一起被复用,复用其中一个可能需要同时考虑同一个包中的其他协作类。通常和业务功能相关。包图•包图用来描述包及其依赖关系。•当表现层包中的类要使用领域包中的领域类提供的服务时,表示包就依赖于领域包。9.2.3子系统•当按照业务功能或管理职能组织包,并对这样的包进行彻底的封装实现后,一个高层的具有特定功能的可以运行的独立构件就产生了,称为子系统(subsystem)•子系统具有自身独立的功能,是物理的具体软件单位,而包只是软件对象的逻辑组织方式•子系统对外可以提供有限的接口,只要接口不改变,不管子系统内部发生什么变化,也不会影响到依赖于该子系统接口的其他子系统。•子系统及其关系使用构件图描述子系统的关系•财务子系统将内部操作进行了封装,但对外提供必要的接口(比如一组函数)•销售子系统在执行销售业务过程中可以使用该接口对销售数据执行某些财务操作。对于销售子系统而言,依赖的是财务子系统的接口,并不需要关心财务子系统的具体实现。9.3设计软件类•软件类是设计阶段中讨论的对象和类,也称为设计类。•软件类的设计的依据:–来源于分析模型中的领域类:它们通常是现实事物或概念的抽象,这些类要转换为软件世界中的类,能够通过OOP实现–计算机操作需要的类:比如为了完成用例所描述的功能,需要添加一些窗口界面类。复杂用例可能涉及到多个领域类的协作,添加控制类实现部分复杂控制流……9.3.1根据分层设计软件类•从分析模型的领域类导出设计阶段中的实体类•增加边界类和控制类完成程序的交互和控制。•为了分辨出类的这三种不同类型,可以采用UML提供的扩展机制——构造型(stetreotype)及其表达符号来定义模型元素构造型Rose中不同构造型的图符边界类实体类控制类系统边界对象行为的控制和协调系统服务和信息分层的软件类协作实现一个用例1、边界类•边界类的职责是完成系统与其参与者之间的交互。–接收来自用户和外部系统的信息与请求–将信息与请求提交给用户和外部系统•通过用例图可以得知每个边界类至少应该与一个参与者有关,参与者类型不同,边界类的设计也不同•边界类包括屏幕窗口、通信接口、打印机接口、传感器、终端以及专用API(应用程序编程接口)等软件对象。–对于图书馆系统来说,参与者都是系统用户,因此边界类只有窗口界面这一种形式。–假如考虑提供馆际互借业务,那么系统就会产生与其他外部合作的图书馆系统的交互,这时与外部系统间的通信接口也是一种边界类识别边界类:图书管理员«boundary»:借书用户界面图书管理员借出图书•根据用例图,每个参与者与一个用例交互,必定导出一个边界类2、实体类•实体类来源于领域模型中的类。•实体类是一个软件对象,表示了领域对象的信息,以及具有与它所表示的信息有关的复杂行为。•实体类反映的信息需要在系统中进行处理,并需要进行持久化存储。边界类和实体类的交互•边界类仅负责数据的输入和输出,不应承担和数据处理有关的业务逻辑•边界类通过与实体类的交互,获得有关数据处理的结果:图书管理员验证«boundary»:借书用户界面«entity»:读者3、控制类•控制类代表协调、排序、事务处理以及对其他对象的控制,经常用于封装与某个具体用例有关的控制流。•控制类处理和协调主要的动作和控制流,并将任务委派给其他对象。•根据分层原则,控制类不封装与参与者交互有关的内容,也不封装与系统处理的长效持久的信息有关的问题,这些问题分别由边界类和实体类进行封装。识别控制类•当用例逻辑较为复杂,并涉及到多个实体类时,可以考虑采用控制类•简化方案:控制类的职责合并给边界类获取验证:图书管理员创建«boundary»:借书用户界面«control»:借书控制类«entity»:读者«entity»:资源项目«entity»:借书记录不同类的职责分配向下依赖的关系:•边界类–负责与参与者的交互(输入数据、显示数据)–为GUI的每个弹出式屏幕创建一个边界对象。•控制类(可选)–负责一个用例的事件流,或部分复杂数据流•实体类–负责数据的封装–为每个领域类创建一个实体类图书馆系统的界面类图书馆系统的控制类图书馆系统的实体类9.3.2详细设计类的属性1.属性类型和初值•属性的类型和默认的初始值应该在设计模型中表示出来。类型和属性名之间用冒号隔开,等号之后写初值。选择的数据类型最好是目标语言中可用的。2.属性的可见性•类中的每个属性可以有可见性定义,指定该属性可以被其他类利用的程度,•UML定义了4种属性可见性:•公有(public)“+”•受保护(protected)“#”•私有(private)“-”•包(package)“~”图书馆类图ResourceItem-itemID:String-state:IntegerLoan-lendDate:Date-dueDate:Date-returnDate:DateOverdue-overDays:Integer-chargeFine:doubleResourceTitle-ISBN:String-titleName:String-author:String-publisher:String-publishDate:Date-price:Double-abstract:String-collectNum:Integer-available:IntegerFineRule-overDueFine:Single-detroyFine:Single-loseFine:SingleReader-cardNo:String-readerName:String-idCardNo:String-address:String-bookLimitation:Integer-bookCurrLmt:Integer-discLimitation:Integer-discCurrLmt:IntegerBooksize:StringDiscdiscType:Stringquantity:Integer9.3.3建立用户界面原型•用户界面原型是一个草图,包含用例提到的系统和用户进行交互的必要元素•界面原型不描述太多细节,通常包含以下内容:–需要由用户输入到系统中的数据窗口或表格;–需要由系统执行的操作按钮;–系统应及时做出回应的事件;–需要由系统输出给用户的数据窗口或消息。图书馆系统的借书界面图书馆系统的还书界面交互对话设计9.3.4详细设计类的方法•每个软件类都有行为,这些行为是它们应承担的职责,也就是OOP中软件类的方法。•职责是在对象设计过程中被分配给类的,该过程是用例驱动的•通过对用例进行实现,可以构造出系统最重要的的动态模型——顺序图或通信图完整的交互模型交互