C+程序设计-对象分册第8章.ppt
2023/9/30,1,本章学习重点掌握内容:面向对象的分析 面向对象的设计与实现,第8章面向对象程序设计方法与实例,2023/9/30,2,第8章面向对象程序设计方法与实例,8.1 面向对象方法学概述 8.2 面向对象的模型 8.3 面向对象程序设计过程 8.4 电梯模拟系统,2023/9/30,3,8.1 面向对象方法学概述,面向对象(Object-Oriented,缩写为OO)方法学的出发点和基本原则,是尽可能模拟人类习惯的思维方式,使开发软件的方法与过程尽可能接近人类认识世界解决问题的方法与过程,也就是使描述问题的问题空间(也称为问题域)与实现解法的解空间(也称为求解域)在结构上尽可能一致。面向对象方法是一种新的思维方法,它不是把程序看作是工作在数据上的一系列过程或函数的集合,而是把程序看作是相互协作而又彼此独立的对象的集合。每个对象就像一个微型程序,有自己的数据、操作、功能和目的。,2023/9/30,4,8.1 面向对象方法学概述,面向对象(Object-Oriented,缩写为OO)方法学的出发点和基本原则,是尽可能模拟人类习惯的思维方式,使开发软件的方法与过程尽可能接近人类认识世界解决问题的方法与过程,也就是使描述问题的问题空间(也称为问题域)与实现解法的解空间(也称为求解域)在结构上尽可能一致。面向对象方法是一种新的思维方法,它不是把程序看作是工作在数据上的一系列过程或函数的集合,而是把程序看作是相互协作而又彼此独立的对象的集合。每个对象就像一个微型程序,有自己的数据、操作、功能和目的。,2023/9/30,5,8.1 面向对象方法学概述,面向对象方法在概念和表示方法上的一致性,保证了软件工程各项开发活动之间的平滑(“无缝”)过渡。面向对象开发过程的核心是面向对象分析(OOA)和面向对象设计(OOD)两个阶段,但二者的界限比较模糊。OOA通过分析用例,提取用户的需求,从而建立问题域逻辑模型的过程;OOD是建立面向对象的求解域模型的过程。从OOA到OOD实际是一个多次反复、逐步迭代模型的过程。面向对象(OO)是认识事物的一种方法,是一种以对象为中心的思维方式。这里先介绍它的几个主要概念:对象、类、封装、继承、消息、结构与关联、多态性。,2023/9/30,6,1、对象 世界上所有的事物都可以称为对象。对象可以是有形的如:一台电视机等。也可以是无形的如:帐户、一项记录等。对象具有静态特征和动态特征。对象是封装了数据结构及可以施加在这些数据结构上的操作的封装体,这个封装体有可以唯一地标识它的名字,而且向外界提供一组服务(即公有的操作)。属性和操作是对象的两大要素。属性是对象静态特征的描述,操作是对象动态特征的描述。对象名也称为对象标识。如电视的属性有:品牌、尺寸、重量等。操作有:收视、选台、音量调节等。,8.1.1 对象和类,2023/9/30,7,2、类 类是对象的蓝图。根据抽象的原则对客观对象进行归纳和划分,把具有相同特征的对象归为一个类。它是一个抽象的概念。类是对象模版,用于创建具有相同属性和相同操作(服务)的对象。它包括属性和方法(注:类的服务、行为和操作只是叫法上的区别)。3、封装 封装是指按照信息隐藏的原则,把对象的属性和操作结合在一起,构成一个独立的封装体。封装性也就是信息隐藏,通过封装把对象的实现细节对外界隐藏起来了。,8.1.1 对象和类,2023/9/30,8,外部对象不能直接操作对象的属性,只能使用对象提供的接口。具有封装性的条件如下:有一个清晰的边界。所有私有数据和实现操作的代码都被封装在这个边界内,从外面看不见更不能直接访问。有确定的接口(即协议)。接口就是对象之间通信的桥梁,只能通过向对象发送消息来使用它。受保护的内部实现。实现对象功能的细节(私有数据和私有方法)不能在定义该对象的类的范围外进行访问。,8.1.1 对象和类,2023/9/30,9,4、继承 继承使得一个类可以继承另一个类的属性和方法。这样通过抽象出共同的属性和方法组建新的类,便于代码的重用。如图8.1的继承关系。,8.1.1 对象和类,图8.1 继承中的父子类,2023/9/30,10,子类电梯按钮和楼层按钮继承了父类Button的全部属性和服务,同时又具有自身新的属性和服务。一般和特殊是相对而言的,在哺乳动物和狗及猫之间,哺乳动物是一般类(称为基类、超类或父类),狗和猫是特殊类(也称子类);在狗和黑狗之间狗是一般类,黑狗是特殊类。5、消息 向某个对象发出的服务请求称作消息。对象提供的服务规定的消息格式称作消息协议。消息包括:被请求的对象标识、被请求的服务标识、输入信息和应答信息。如:向电梯按钮类发送请求按下电梯按钮的消息elvatorButton.pressButton()。,8.1.1 对象和类,2023/9/30,11,8.1.1 对象和类,6、结构与关联 一个系统一般由很多对象组成,对象之间并不是互相孤立的,而是存在着各种各样的关系。包括:部分/整体、一般/特殊、实例连接、消息连接。(1)部分/整体 对象之间存在的部分与整体的结构关系。如电梯按钮是电梯类的一个组成部分,电梯由电梯按钮、门、楼层、响铃等组成。如图8.2的组合关系。,2023/9/30,12,8.1.1 对象和类,图8.2 组合关系,2023/9/30,13,8.1.1 对象和类,组合和聚合。组合关系中部分和整体的关系很紧密。聚合关系中则比较松散,一个部分对象可以属于几个整体对象。(2)一般/特殊 对象之间的结构关系,很多时候也称作泛化和特化关系。(3)实例连接 对象之间的实例连接称作链接,对象类之间的实例连接称作关联。(4)消息连接 消息连接表现了这样一种联系:一个对象发送消息请求另一个对象的服务,接收消息的对象响应消息,执行相应的服务。,2023/9/30,14,7、多态性 所谓多态性是指不同对象接收相同的消息时产生不同的行为。这里的消息主要是对类中成员函数的调用,而不同的行为就是指类成员函数的不同实现。即在类等级的不同层次中可以共享(公用)一个行为(方法)的名字,然而不同层次中的每个类却各自按自己的需要来实现这个行为。当对象接收到发送给它的消息时,根据该对象所属于的类动态选用在该类中定义的实现算法。如图8.1中,当向按钮对象发送消息pressButton()时,不同按钮对象如电梯内部按钮和楼层按钮会自动判断自己的所属类并执行相应的服务。,8.1.1 对象和类,2023/9/30,15,面向对象的模型,分别从三个不同侧面描述了所要开发的系统。对象模型定义了“做什么”的实体,功能模型指明了系统应该“做什么”,动态模型明确规定在何种状态下,接受什么事件的触发而“做什么”。一个典型的软件系统组合了上述三方面内容:它使用数据结构(对象模型),执行操作(动态模型),并且完成属性值的变化(功能模型)。,8.2 面向对象的模型,2023/9/30,16,1.对象模型是一个类(属性和方法)、对象(类的实例)、类或对象之间关系的定义集。对象模型表示静态的、结构化系统的“数据”性质,为建立动态模型和功能模型提供了实质性的框架。对象模型把面向对象的概念与常用的信息建模概念结合起来,增强了模型的可理解性和表达能力。对象模型还表示了类/对象之间的结构关系。类/对象之间的关系一般可概括为关联、归纳(继承)、组合(或聚集)三类。,8.2 面向对象的模型,2023/9/30,17,8.2 面向对象的模型,2.动态模型表示瞬间的、行为化的系统“控制”性质,它规定了对象模型中对象状态的合法变化序列。对象有自己的生命周期,它由多个阶段组成,每个特定阶段都有规范该对象行为的一组运行规则。对象的状态是对象属性的一种抽象,事件是某个特定时刻发生的一个系统行为是引起对象状态转换的控制信息。对象对事件的响应,取决于当时的状态,响应包括改变自己的状态,或者是形成一个新的触发行为(事件)。动态模型描绘对象的状态,触发状态转换的事件,以及对象行为(对事件的响应),即基于事件共享而互相关联的一组状态集合构成了系统的动态模型。,2023/9/30,18,3.功能模型指明了系统应该“做什么”,直接地反映了用户对目标系统的需求。面向对象的功能模型由一组用例组成,用例模型描述的是外部执行者(Actor)所理解的系统功能。用例模型描述了待开发系统的功能需求 用例模型将系统看作黑盒,从外部执行者的角度来理解系统用例模型驱动了需求分析之后各阶段的开发工作,不仅在开发过程中保证了系统所有功能的实现,而且被用于验证和检测所开发的系统,从而影响到开发工作的各个阶段和 UML 的各个模型。在UML中,一个用例模型由若干个用例图描述,用例图主要元素是用例和执行者。,8.2 面向对象的模型,2023/9/30,19,传统程序设计方法的主要思想是自顶向下逐步分解。整个系统由分层的子程序集合构成。这要求程序设计师必须对系统的调用关系非常清楚,这对于开发大型系统来讲是是非困难的,而且构建的系统稳定性较差,任何上层子程序的修改都会引整个系统的改变。而面向对象得程序设计方法提供一种崭新的系统设计方案,就是将系统看成一系列相关联的对象的集合,而对象之间是通过消息传递的方法相互作用来完成任务,每个对象用自己的方法管理数据。本节就介绍这种软件开发的方法,它将软件开发过程分为3个阶段:面向对象的分析、面向对象的设计、面向对象的实现。不同阶段则使用不同的模型来描述。,8.3 面向对象程序设计过程,2023/9/30,20,8.3.1 面向对象的分析,面向对象分析的任务是确定系统能够做什么?谁来使用这个系统?同时建立用例模型,并定义系统中的问题领域类,主要由系统用户和开发人员合作完成。1需求分析 分析的第一步是定义用例,以描述所开发系统的外部功能需求。用例模型的主要构件是用例、角色和系统边界。用例用于描述系统所有功能需求,系统边界用于界定系统功能的范围,而角色用于描述与系统功能有关的外部实体,它可以是用户,也可以是外部系统。,2023/9/30,21,使用面向对象程序设计方法时,在本阶段不需要严格的系统规格说明书,可以使用图表(如用例图)来描述系统的功能,除了用用例图描述系统需求外,还可以用文字(或活动图)对每个用例进行需求说明,更具体地描述该用例与角色的交互。例如电梯模拟系统的用例图如下:,8.3.1 面向对象的分析,2023/9/30,22,8.3.1 面向对象的分析,图8.3 电梯模拟系统用例图,2023/9/30,23,2特定领域类分析 分析阶段的另一项工作是特定领域分析,以列出系统中的特定领域类。我们可以通过阅读规格说明、用例以及寻找系统处理的概念来进行特定领域分析,也可以通过用户和领域专家的讨论,以识别出要处理的所有关键类及它们的相互关系。这里的特定领域是指具体的商业领域,而不是整个系统领域。在本实例中,可以确定电梯模拟系统中特定领域类为电梯、调度、门、按钮、楼层等,并使用类图来描述系统领域类及其关系。,8.3.1 面向对象的分析,2023/9/30,24,需要强调的是,这一阶段对特定领域类的描述具有一定的素描性质,也就是说特定领域类的操作和属性不一定与最终实现时的定义一致。因为此时还没有涉及到系统功能的具体实现,不可能准确、完整地定义它们。有一些操作需要在设计阶段细化时才能确定。此外,为了描述问题领域中类的动态行为,可以使用UML中的任何一种动态图(如顺序图、活动图、协作图、状态图)。本阶段的各动态图都具有素描性质,主要是为了协助对领域类及其相互关系的分析,为下一阶段的具体设计打下基础。,8.3.1 面向对象的分析,2023/9/30,25,设计阶段的任务是对分析模型进行扩展并将模型进一步细化,并考虑技术细节和限制条件。设计的目的是指定一个可行的解决方案,以便能很容易地转变成为编程代码。设计可以分成两个阶段:体系结构设计阶段(ArchitectureDesign)。这是一个从较高层次的进行的设计,用来定义包(子系统),描述包之间的依赖性及通信机制。很自然,目的是要设计一个清晰简单的体系结构,有很少的依赖性,而且尽可能避免双向依赖。详细设计阶段(Detailed Design)。在此阶段,所有的类都详尽地进行描述,给编写代码的程序员一个清晰的规范说明。UML中的动态模型用来说明类的对象如何在特定的情况下做出相应的表现。,8.3.2 面向对象的设计,2023/9/30,26,8.3.2 面向对象的设计,1体系结构设计 类图中包括有助于用户从技术逻辑中分离出应用逻辑(领域类),从而减少它们之间的依赖性。这就是软件结构设计强调的模块间的高聚合、低偶合的原则。在商业MIS中,存在以下包(或子系统):用户接口包:用户接口类允许用户访问系统数据和加入新数据。在商业对象中,用户接口包跟商业对象包合作,调用商业对象的操作,实施数据的检索和插入。,2023/9/30,27,8.3.2 面向对象的设计,商业对象包:该包包括域类,这些域类(如elevatorButton,Floor,Light等)来自于分析模型。设计阶段完整地定义了这些类的操作,并增加了一些其他细节来支持持续存储。在设计阶段,详细设计这些类,以完整定义他们的操作,支持对数据库的存取。所以,所有商业对象类必须继承数据库包中的类。数据库包:它向商业对象包中的类提供服务,以便他们能够持续地存储。在当前版本中,持久对象类将把它的子类的对象存储到文件系统的文件中。通用包:该包含了一些服务,用来被系统中其他包调用。,2023/9/30,28,8.3.2 面向对象的设计,2详细设计 详细设计的目的是通过创建新的类图、状态图和动态图,描述新类,并扩展和细化分析阶段“素描”的商业对象类。不过在详细设计阶段,它们是从技术层次上对系统进行更详尽的描述。如分析阶段的用例描述用来验证它们是否在设计阶段都得到处理,而顺序图用来展示系统中每个用例在技术上如何实现,等等。在设计阶段,也可细化分析阶段的状态图,更详细的显示状态的变换细节。使用状态图可以揭示单个对象在整个系统中的变化细节,对了解和实现关键类有较大的帮助。此外,还可以使用其他图在实现层上从不同侧面对分析阶段建立的模型进行细化。,2023/9/30,29,8.3.3 面向对象的实现,面向对象的实现可分为两个阶段:一是对类进行编程的过程。可以选择某种面向对象对象编程语言(如c+或Java)作为实现系统的软件环境;二是测试和配置,完成系统编码后,需要对系统进行测试。1.编码 本阶段完成系统框架进行编码。选择合适的语言实现设计阶段完成的总体框架的搭建和具体算法的描述。在实现阶段中,可以选取下列图的说明来辅助编程:,2023/9/30,30,类的规格说明:每个类的规格说明详细显示了必要的属性和操作。类图:显示类的静态结构和类之间的关系。状态图:显示类的对象可能的状态、所需处理的转移以及触发这些转移的操作。包含某个类的对象的动态图(顺序图、协作图、活动图):显示该类的某个方法的实现或别的对象是如何使用该类的对象的。用例图和规格说明:显示系统需求和结果。,8.3.3 面向对象的实现,2023/9/30,31,编码期间也可能会发现设计模型的缺陷。这时需要开发者修改设计模型。修改设计模型时一定要保持设计模型与编码的一致性,以便将来易于维护。2测试和配置 完成系统编码后,需要对系统进行测试,它通常包括:单元测试、集成测试、系统测试和验收测试。在单元测试中使用类图和类的规格说明,对单独的类或一组类进行测试;在集成测试中,使用组件图和协作图,对各组件的合作情况进行测试;在系统测试中,使用用例图,以检验所开发的系统是否满足例图所描述的需求。,8.3.3 面向对象的实现,2023/9/30,32,8.4.1 需求陈述 电梯模拟系统的设计与“真实”的系统相比省去很多技术的细节。我们的电梯系统有所有电梯都有的基本功能,如上升和下降,开门和关门,以及能承载乘客。电梯假设在一栋大楼的第一层到第N层运行,第一层是大厅。电梯里有每一层对应的按钮,除了第一层和第N层外,每个楼层都有两个按钮,乘客可以呼叫上楼和下楼。顶楼只有一个下行按钮,第一层的大厅只有一个上行按钮。当电梯停在某一层时,电梯开门,电梯的指示灯表明当前电梯运行的方向,这样乘客知道当前电梯运行的方向。电梯在两个楼层间快速移动时,电梯的门是紧闭的,而且电梯能提前减速到达目的地。为保证电梯系统的安全,在任何不安全的因素下,紧急制动就会促发,电梯被强制停止。,8.4 电梯模拟系统,2023/9/30,33,电梯到达一个楼层时,它会重置电梯按钮,并响铃(继承到电梯内部)进入电梯,然后电梯向楼层发布已经到达的信号。作为响应,楼层会重置楼层按钮,并显示电梯已经到达指定楼层。然后,电梯门开,注意楼层上对应的门随电梯门一起自动打开。随后,电梯内的乘客离开电梯,正在等待电梯的人进入电梯。一个人进入电梯内后,按下电梯按钮,电梯内的指示灯会亮。另外,等电梯到达另一楼层,并重置电梯按钮后,灯就熄灭。接着,电梯向指定楼层移动,电梯到达指定楼层后,如果没有人进入电梯,而且楼层上的楼层按钮没有被按下的话,就等待电梯门关闭,直到楼层按钮被按下。,8.4.1 需求陈述,2023/9/30,34,用例图 电梯系统的用例图如图8.4所示,主要包括用例、角色和关系。,8.4.2 电梯模拟系统的分析,图8.4 电梯系统用例图,2023/9/30,35,其中的小人代表参与系统的外来实体,在这就是电梯系统的唯一角色-乘客,它需要系统为他提供相应的服务,乘客通过观察电梯移动的方向和电梯位置指示器决定是否进/出电梯,因此他参与系统的四个用例,处理电梯呼叫、处理楼层呼叫、标示电梯位置和标志移动方向。以下是该用例图的简单功能描述。,8.4.2 电梯模拟系统的分析,2023/9/30,36,处理电梯呼叫:这个用例包括几个场景。这些场景有乘客的呼叫电梯、电梯按钮的亮灭、电梯控制器处理电梯呼叫,处理按钮信息更新等等。处理楼层呼叫:和处理电梯呼叫类似,这个用例包括乘客选择楼层、楼层按钮的亮灭和电梯控制器处理楼层呼叫,处理按钮信息更新等等。移动停止电梯:这是一台电梯的主要功能,详细的动作包括驱动速度的改变,停止的判定,电梯的运动方向驱动。标识电梯移动方向:电梯应该有这种机制,即让乘客知道电梯目前的运动方向,决定是否进电梯。,8.4.2 电梯模拟系统的分析,2023/9/30,37,标识电梯位置:类似电梯移动方向,电梯应该让乘客知道他/她的目的层是否到达,决定是否离开电梯。开关门:乘客进出电梯,电梯应该开关门。这个用例应该包括当电梯正关闭时乘客想进入,乘客可以使电梯门打开。触发紧急制动器:电梯有安全机制确定一个不安全的状态不是瞬时产生的。系统框架(用例图中封闭的矩形)包含系统的用例,而边界代表系统和外界实体交互的界面。,8.4.2 电梯模拟系统的分析,2023/9/30,38,每个用例代表系统对外提供的服务,或另一个子系统。可用事件流对其中的用例进行详细描述。如下对用例“处理电梯呼叫“:处理电梯呼叫用例基本流程。(1)乘客按下第M层的下行按钮。(2)M被插入到下行队列的合适位置。(3)如果M被插到下行队列头。如果电梯正处于下行状态。将M发送给电梯作为目的地。如果电梯处于停止状态。将M发送给电梯作为目的地。(4)电梯到达此楼层。(5)电梯自动打开门。(6)乘客进入电梯。(7)超重响警铃。,8.4.2 电梯模拟系统的分析,2023/9/30,39,类图 类图是面向对象系统中应用最多的图,它对系统进行静态建模。静态图主要描述系统的功能需求-系统给最终用户提供的服务。类图描述一组类、接口和协作,及它们的关系。类图包括整个系统的描述,如系统的结构和细节,还有类的属性和操作等细节。具体方法如下:,8.4.2 电梯模拟系统的分析,2023/9/30,40,1.找出问题陈述中所有的名词 表8-1 问题陈述中的名词 大楼 乘客 载客量 电梯 楼层 电梯按钮 楼层按钮 电梯模拟程序 楼层电梯指示灯 人(电梯内的人,楼层等电梯的人)时间 铃 电梯门 时钟问题陈述中的名词,8.4.2 电梯模拟系统的分析,2023/9/30,41,2.选择在系统中担负主要职责的名词,而去掉下面的词 电梯模拟程序 载客量 时间 建筑物是与系统无关的事物,时间和载客量分别是时钟和电梯所具有的特性,而非独立的实体,电梯模拟程序是以完整的程序,而不是一个具体的实体,8.4.2 电梯模拟系统的分析,2023/9/30,42,3.将剩下的名词划成不同的类,以确定真正的类 大楼 楼层 门 按钮(电梯和楼层按钮)灯 时钟 调度 铃 乘客(包括电梯内的人,楼层等电梯的人)它们都可能成为系统中所涉及的最终类。我们为楼层按钮和电梯按钮创建一个类,按钮类,并拥有两个子类,分别为楼层按钮和电梯按钮(他们分别在电梯系统中担负主要职责,分别管理呼唤电梯和指挥电梯的移动)。系统主要的类有:大楼,楼层,门,按钮),灯,时钟,调度,铃,乘客。,8.4.2 电梯模拟系统的分析,2023/9/30,43,电梯系统类图 根据上面的分析得出系统的类图。如电梯类图、电梯按钮和门类:门:“电梯”对象-电梯控制器-命令门打开和关闭,这和用例中的描述相对应。电梯:电梯在控制下上升和下降(用不同的速度),需要时可以停下。按钮:电梯控制器类也控制按钮类,按钮类生成两个子类电梯按钮类和楼层按钮类)。控制对象和按钮对象通信,得到按钮是否被按下,反过来控制按钮灯的发光。,8.4.2 电梯模拟系统的分析,2023/9/30,44,8.4.2 电梯模拟系统的分析,8.5 电梯类图,1 拥有 1 拥有*1,2023/9/30,45,8.4.2 电梯模拟系统的分析,系统由不同的类组成,类间的关系称为类的关联,通过类之间的消息传递才构成纷繁复杂的软件系统。Uml通过类图描述类之间的关联,如图中继承关联(楼层按钮合电梯按钮的关系),组合关联(电梯和门以及电梯按钮的关系),一般关联(电梯和门的关系等)。关联可表示为关联对象的个数和关联名,如电梯和电梯按钮的关联表示。系统类图如下:,2023/9/30,46,8.4.2 电梯模拟系统的分析,图8.6 电梯模拟系统的类图,1 调 度 0.1 0.1 等待 乘 1 坐 1 拥有 1 1 1.2 1.2 1.*1,2023/9/30,47,类的属性 确定类的结构以后,需要表述类本身具有的特性,也就是类的属性。通过对用例图中每个用例的详细表述中查询每个类对象拥有的属性,并用合适的名词描述属性。可用一张表格描述在需求中每个类相关的描述。如下表8-2:,8.4.2 电梯模拟系统的分析,2023/9/30,48,8.4.2 电梯模拟系统的分析,表8-2 电梯模拟系统中类的相关描述,2023/9/30,49,8.4.2 电梯模拟系统的分析,命名类的属性:包括属性的名字、类型、初始值,如图8.7表示:,图8-7 具有属性的类图,2023/9/30,50,8.4.2.5 类的行为 行为是指为了完成某一任务,一个对象提供的、并体现其责任的操作。同类对象之间和不同的对象之间通过相互通信来完成复杂的系统状态的控制。行为的获取类的方法仍旧从用例图中的每个用例入手,通过对用例中每个场景的详细分析区或去每个对象所拥有的职责,具体从三个方面完成类的行为的获取。(1)提取对象外部行为的大致功能和名称,同时进行适当的精化;(2)标识对象之间的消息传递;(3)使用模板描述对象的外部服务和对象间的消息传递。所谓模板是软件组织制定的用于描述对象行为的标准格式。,8.4.2 电梯模拟系统的分析,2023/9/30,51,8.4.2 电梯模拟系统的分析,表8-3 电梯模拟系统中类的行为描述,2023/9/30,52,8.4.2 电梯模拟系统的分析,根据以上描述命名类的行为,包括行为的名字,返回类型和参数。如图8.8表示:,图8.8 具有属性和行为的类图,2023/9/30,53,设计阶段的主要任务是定义包(子系统),包括包间的依赖性和主要通信机制,以及细化包的内容,使编程人员得到所有类的一个足够清晰的描述。同时使用UML中的动态模型,描述特定情况下这些类的实例之间的行为。1结构设计 本系统较为简单,仅给 出类间的包含关系和系统结构图。根据系统需要,添加控制类Building类,完成对电梯的总控,各类的关系如图8.9:,8.4.3 电梯模拟系统的设计与实现,2023/9/30,54,8.4.3 电梯模拟系统的设计与实现,图8.9 添加控制类后的系统类图,0.1 乘坐 11,0.1 等待 1,1 1,1,2023/9/30,55,各类的详细声明如下:(1)Building(电梯模拟的总控)类:它是整个电梯模拟系统的控制类,每一秒钟,该类接收时钟信息,并建立计划分配表给Scheduler类,给电梯发送指定的时间,同时启动电梯的运行。它由Floor 类、Elevator类、Clock类、Scheduler类对象组成。方法:runSimulation(int),按设定的时间模拟电梯运行(2)Bell(响铃)类:电梯到达指定位置时产生铃声提示。方法:ringBell(),响铃。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,56,(3)Clock(时钟)类:电梯运行中时间的获取和时间设置。方法:tick(),按每一秒增加时钟。getTime(),获取时钟当前时间。(4)Door(门)类:电梯到达指定楼层时,乘客乘坐电梯时实现电梯门的开关,通知乘客进入或退出电梯。方法:openDoor(Person*const,Person*const,Floor&,Elevator&),在电梯到达指定楼层时打开门。closeDoor(const Floor&),在电梯到达指定楼层,乘客进入电梯后实现关门。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,57,(5)Floor(楼层)类:电梯到达的楼层,以及乘客等待的楼层,通知楼层按钮完成楼层按钮的操作,并通知指示灯开关。方法:isOccupied(),调度发送消息,电梯被占,乘客需等待一段时间。getNumber(),返回楼层的层数。elevatorArrived(),通知楼层电梯到达。elevatorLeaving(),通知楼层电梯离开。(6)Light(指示灯)类:楼层按钮和电梯按钮按下和恢复原状后显示状况的灯。方法:turnOn(),开灯。turnOff(),关灯。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,58,(7)Person(乘客)类:乘坐电梯的乘客,分别完成对电梯按钮和楼层按钮的操作,以及进入和离开电梯时通知电梯完成相应动作。方法:stepOntoFloor(Floor(8)FloorButton(楼层按钮)类:召唤电梯,标示电梯的移动方向。方法:pressButton(),按下楼层按钮。resetButton(),复原楼层按钮。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,59,(9)ElevatorButton(电梯按钮)类:提供电梯移动的服务。方法:pressButton(),按下电梯内按钮。resetButton(),松开按钮电梯内按钮。(10)Elevator(电梯)类:电梯模拟系统的主要类,由Floor类、Person类、Door类和Bel类组成。实现电梯的移动和电梯到达指定位置后和其他类的交互,并响铃。方法:summonElevator(int floor),呼唤电梯完成一特殊楼层的服务。prepareToLeave(bool),电梯准备离开。processTime(int),电梯运行时间。passengerEnters(Person*const),乘客进入电梯。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,60,passengerExits(),乘客离开电梯。processPossibleArrival(),可能到达的电梯。processPossibleDeparture(),电梯可能离开。arriveAtFloor(Floor&),电梯到达指定的楼层。move(),电梯移动。(11)Scheduler(计划表)类:产生随机时间,创建在某一时刻乘坐电梯的乘客。方法:processTime(int),设置时间表。schedulerTime(const Floor&),设置到达指定楼层的计划时间和延时时间。delayTime(const Floor&),到达指定楼层时间延时。createNewPerson(Floor&),获取指定楼层等待电梯的乘客。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,61,2.类的设计 详细设计的目的是通过创建新的类图、顺序图、状态图和动态图,描述新的类图,并扩展和细化分析阶段素描的商业对象类。主要为实现系统的功能定义类中必要的操作,为访问类的属性提供相应的访问接口,对定义好的操作或接口进行优化,另外实现对象间的关联,并给出类的定义。注意:关联通常用指针或指针数组实现,c+中也可以采用引用来实现关联。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,62,2.1 顺序图 顺序图描述对象之间的动态交互关系,着重表现对象间消息传递的时间顺序。顺序图有两个坐标轴:纵坐标轴表示时间,横坐标轴表示不同的对象。顺序图中的对象用一个矩形框表示,框内标有对象名(对象名的表示格式与对象图中相同)。从表示对象的矩形框向下的垂直虚线是对象的“生命线”,用于表示在某段时间内该对象是存在的。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,63,对象间的通信用对象生命线之间的水平消息线来表示,消息箭头的形状表明消息的类型(同步、异步或简单)。当收到消息时,接收对象立即开始执行活动,即对象被激活了。激活用对象生命线上的细长矩形框表示。消息通常用消息名和参数表来标识。消息还可以带有条件表达式,用以表示分支或决定是否发送消息。如果用条件表达式表示分支,则会有若干个互斥的箭头,也就是说,在某一时刻仅可发送分支中的一个消息。图8.10显示了时钟对象、计划表对象和电梯对象之间的交互。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,64,8.4.3 电梯模拟系统的设计与实现,tick()(计算时间值)getTime()(获取当前时间)time processTime(currentTime:int)(设置目前时间)processTime(currentTime:int)(电梯运行时间),图8.10 时钟对象、计划表对象和电梯对象之间的交互的顺序图,2023/9/30,65,2.2 协作图 协作图侧重于描述各个对象之间存在的消息收发关系(交互关系),而不专门突出这些消息发送的时间顺序。寻找对象间的协作。仔细察看表8-3(电梯模拟系统中类的行为描述),寻找消息的发送者和消息的接受者,以判断交互的对象和消息的转递。如:在表中电梯(Elevator类)对象拥有“释放电梯按钮的行为”,要完成该行为,电梯(Elevator类)对象必须电梯按钮(elevatorButton类)对象发送消息resetButton,这就激活了电梯按钮(elevatorButton类)中的操作resetButton,这就表明电梯类的对象和电梯按钮类的对象之间建立了交互关系。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,66,8.4.3 电梯模拟系统的设计与实现,表8-4显示了电梯模拟系统中所有对象之间的交互。,2023/9/30,67,8.4.3 电梯模拟系统的设计与实现,图8.11显示系统中的对象之间的协作图,3.1 resetButton()3.2 turnOn()4.2.1passengerEnter()4.1.1 passengerExits()1.resetButton 2.ringBell()4.2 enterElevator()4.1 exitElevator,2023/9/30,68,8.4.3 电梯模拟系统的设计与实现,2.3 系统中类的声明 有以上的各种图形的分析,可以得出系统所设计的所有类的声明。电梯模拟系统中所涉及的类的声明见表8-5:,2023/9/30,69,8.4.3 电梯模拟系统的设计与实现,所有类的声明分别存放在不同的c+头文件中,电梯模拟系统所涉及的类的头文件如表8-6:,2023/9/30,70,8.4.3 电梯模拟系统的设计与实现,表8-6电梯模拟系统中所涉及类声明的头文件,各头文件的详细声明(略)。,2023/9/30,71,3.对象实现 本系统的对象实现由共bell.cpp、clock.cpp、floor.cpp、door.cpp、elevator.cpp、light.cpp、person.cpp、scheduler.cpp、floorButton.cpp、elevatorButton.cpp、building.cpp、elevator_control.cpp共12个文件组成,其中elevator_control.cpp是主控类,表8-7显示了各个文件的简单说明。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,72,8.4.3 电梯模拟系统的设计与实现,表8-7 电梯模拟系统中所涉及的实现文件声明,2023/9/30,73,现以电梯类为例,简单给出电梯(Elevator)类中各操作的算法描述。Elevator类中主要操作如下:(1)Elevator(Floor&firstFloor,Floor&secondFloor)/电梯类的构造函数,分别在初始化列表中完成组合类电梯按钮类、floor、乘客类、时钟类和响铃类的对象初始化(2)Elevator()/电梯类的析构函数 撤销电梯。,8.4.3 电梯模拟系统的设计与实现,2023/9/30,74,(3)summonElevator(int floor)/呼唤电梯完成一特殊楼层的服务 算法描述:/在某一楼层设置该楼层的电梯呼叫服务。floor=Floor:FLOOR1?floor1NeedsService=true:floor2NeedsService=true;,8.4.3 电梯模拟系统的设计与实现,2023/9/30,75,(4)prepareToLeave(bool leaving)/电梯准备离开 算法描述:/获取当前呼叫电梯的楼层 Floor,8.4.3 电梯模拟系统的设计与实现,2023/9/30,76,(5)processTime(int time)/通过检测电梯到达目的楼下或准备离开某楼层时,更新电梯时间 算法描述:/首先获取当前时钟的时间 currentBuildingClockTime=time;/电梯按预先设定的楼层移动,则调用方法processPossibleArrival()计算到达目的楼层的时间,否则调用processPossibleDeparture()获取电梯离开的时间 if(moving)processPossibleArrival();else processPossibleDeparture();,8.4.3 电梯模拟系统的设计与实现,2023/9/30,77,(6)passengerEnters(Person*const personPtr)/乘客进入电梯/获取当前进入电梯的乘客 passengerPtr=personPtr;coutgetID()进入电梯.currentFloorendl;(7)passengerExits()/乘客离开电梯/当前乘客置空 passengerPtr=0;,8.4.3 电梯模拟系统的设计与实现,2023/9/30,78,(8)processPossibleArrival()/电梯可能到达的楼层 算法描述:/如果时钟获取时间恰好是电梯到达楼层时间,则更新电梯,输出当前楼层 if(currentBuildingClockTime=arrivalTime)currentFloor=(currentFloor=Floor:FLOOR1?Floor:FLOOR2:Floor:FLOOR1);direction=(currentFloor=Floor:FLOOR1?UP:DOWN);cout电梯到达第 currentFloor层e