软件工程ppt 11面向对象设计课件.ppt
第十一章 面向对象设计,面向对象设计的准则启发规则软件重用系统分解设计问题域子系统、人-机交互子系统任务管理子系统、数据管理子系统、类中的服务、关联设计优化,1. 模块化2. 抽象3. 信息隐藏4. 弱耦合 一般说来,对象之间的耦合可分为两大类,下面分别讨论这两类耦合: (1) 交互耦合 (2) 继承耦合,面向对象设计的准则,5. 强内聚内聚衡量一个模块内各个元素彼此结合的紧密程度。也可以把内聚定义为:设计中使用的一个构件内的各个元素,对完成一个定义明确的目的所做出的贡献程度。在设计时应该力求做到高内聚。在面向对象设计中存在下述3种内聚。(1) 服务内聚。一个服务应该完成一个且仅完成一个功能。(2) 类内聚。设计类的原则是,一个类应该只有一个用途,它的属性和服务应该是高内聚的。(3) 一般-特殊内聚。设计出的一般-特殊结构,应该符合多数人的概念,更准确地说,这种结构应该是对相应的领域知识的正确抽取。,6. 可重用软件重用是提高软件开发生产率和目标系统质量的重要途径。重用基本上从设计阶段开始。重用有两方面的含义: 一是尽量使用已有的类(包括开发环境提供的类库,及以往开发类似系统时创建的类),二是如果确实需要创建新类,则在设计这些新类的协议时,应该考虑将来的可重复使用性。,1. 设计结果应该清晰易懂使设计结果清晰、易读、易懂,是提高软件可维护性和可重用性的重要措施。显然,人们不会重用那些他们不理解的设计。保证设计结果清晰易懂的主要因素如下:(1) 用词一致(2) 使用已有的协议(3) 减少消息模式的数目(4) 避免模糊的定义,启发规则,2. 一般-特殊结构的深度应适当应该使类等级中包含的层次数适当。一般说来,在一个中等规模(大约包含100个类)的系统中,类等级层次数应保持为72。不应该仅仅从方便编码的角度出发随意创建派生类,应该使一般-特殊结构与领域知识或常识保持一致。,3. 设计简单的类应该尽量设计小而简单的类,以便于开发和管理。当类很大的时候,要记住它的所有服务是非常困难的。经验表明,如果一个类的定义不超过一页纸(或两屏),则使用这个类是比较容易的。为使类保持简单,应该注意以下几点:(1) 避免包含过多的属性(2) 有明确的定义(3) 尽量简化对象之间的合作关系 (4) 不要提供太多服务,4. 使用简单的协议一般说来,消息中的参数不要超过3个。当然,不超过3个的限制也不是绝对的,但是,经验表明,通过复杂消息相互关联的对象是紧耦合的,对一个对象的修改往往导致其他对象的修改。,5. 使用简单的服务面向对象设计出来的类中的服务通常都很小,一般只有35行源程序语句,可以用仅含一个动词和一个宾语的简单句子描述它的功能。如果一个服务中包含了过多的源程序语句,或者语句嵌套层次太多,或者使用了复杂的CASE语句,则应该仔细检查这个服务,设法分解或简化它。一般说来,应该尽量避免使用复杂的服务。如果需要在服务中使用CASE语句,通常应该考虑用一般-特殊结构代替这个类的可能性。,6. 把设计变动减至最小通常,设计的质量越高,设计结果保持不变的时间也越长。即使出现必须修改设计的情况,也应该使修改的范围尽可能小。理想的设计变动曲线如下图所示:,1.概念1)重用重用也叫再用或复用,是指同一事物不作修改或稍加改动就多次重复使用。广义地说,软件重用可分为以下3个层次:(1) 知识重用 (2) 方法和标准的重用(3) 软件成分的重用2)软件成分的重用级别软件成分的重用可以进一步划分成以下3个级别:,软件重用,(1) 代码重用通常把它理解为调用库中的模块。实际上,代码重用也可以采用下列几种形式中的任何一种:源代码剪贴:这是最原始的重用形式。继承:利用继承机制重用类库中的类时,无须修改已有的代码,就可以扩充或具体化在库中找出的类,因此,基本上不存在配置管理问题。(2) 设计结果重用设计结果重用指的是,重用某个软件系统的设计模型(即求解域模型)。 (3) 分析结果重用这是一种更高级别的重用,即重用某个系统的分析模型。,3)典型的可重用软件成分可能被重用的软件成分主要有以下10种:(1) 项目计划(2) 成本估计(3) 体系结构(4) 需求模型和规格说明(5) 设计(6) 源代码(7) 用户文档和技术文档(8) 用户界面(9) 数据(10) 测试用例,利用面向对象技术,可以更方便更有效地实现软件重用。面向对象技术中的“类”,是比较理想的可重用软构件,不妨称之为类构件。类构件有3种重用方式,分别是实例重用、继承重用和多态重用。1)可重用软构件应具备的特点为使软构件也像硬件集成电路那样,能在构造各种各样的软件系统时方便地重复使用,就必须使它们满足下列要求。(1) 模块独立性强(2) 具有高度可塑性 (3) 接口清晰、简明、可靠精心设计的“类”基本上能满足上述要求,可以认为它是可重用软构件的雏形。,2.类构件,2)类构件的重用方式(1) 实例重用(2) 继承重用(3) 多态重用,1)质量理想情况下,为了重用而开发的软件构件已被证明是正确的,且没有缺陷。事实上,由于不能定期进行形式化验证,错误可能而且也确实存在。但是,随着每一次重用,都会有一些错误被发现并被清除,构件的质量也会随之改善。随着时间的推移,构件将变成实质上无错误的。,3. 软件重用的效益,2)生产率当把可重用的软件成分应用于软件开发的全过程时,创建计划、模型、文档、代码和数据所需花费的时间将减少,从而将用较少的投入给客户提供相同级别的产品,因此,生产率得到了提高。由于应用领域、问题复杂程度、项目组的结构和大小、项目期限、可应用的技术等许多因素都对项目组的生产率有影响,因此,不同开发组织对软件重用带来生产率提高的数字的报告并不相同,但基本上30%50%的重用大约可以导致生产率提高25%40%。,3)成本软件重用带来的净成本节省可以用下式估算:C=Cs-Cr-Cd其中,Cs是项目从头开发(没有重用)时所需要的成本;Cr是与重用相关联的成本;Cd是交付给客户的软件的实际成本。Cr主要包括下述成本:领域分析与建模的成本;设计领域体系结构的成本;为便于重用而增加的文档的成本;维护和完善可重用的软件成分的成本;为从外部获取构件所付出的版税和许可证费;创建(或购买)及运行重用库的费用;对设计和实现可重用构件的人员的培训费用。,人类解决复杂问题时普遍采用的策略是,“分而治之,各个击破”。同样,软件工程师在设计比较复杂的应用系统时普遍采用的策略,也是首先把系统分解成若干个比较小的部分,然后再分别设计每个部分。系统的主要组成部分称为子系统。通常根据所提供的功能来划分子系统。各个子系统之间应该具有尽可能简单、明确的接口。在划分和设计子系统时,应该尽量减少子系统彼此间的依赖性。,系统分解,可以把面向对象设计模型的4大组成部分想象成整个模型的4个垂直切片。典型的面向对象设计模型可以用下图表示:,1. 子系统之间的两种交互方式在软件系统中,子系统之间的交互有两种可能的方式,分别是客户-供应商(Client-supplier)关系和平等伙伴(peer-to-peer)关系。(1) 客户-供应商关系在这种关系中,作为“客户”的子系统调用作为“供应商”的子系统,后者完成某些服务工作并返回结果。(2) 平等伙伴关系在这种关系中,每个子系统都可能调用其他子系统,因此,每个子系统都必须了解其他子系统的接口。,2. 组织系统的两种方案(1) 层次组织层次结构又可进一步划分成两种模式:封闭式和开放式。所谓封闭式,就是每层子系统仅仅使用其直接下层提供的服务。但是,开放模式的系统不符合信息隐藏原则,对任何一个子系统的修改都会影响处在更高层次的那些子系统。设计软件系统时到底采用哪种结构模式,需要权衡效率和模块独立性等多种因素,通盘考虑以后再做决定。(2) 块状组织这种组织方案把软件系统垂直地分解成若干个相对独立的、弱耦合的子系统,一个子系统相当于一块,每块提供一种类型的服务。,3. 设计系统的拓扑结构由子系统组成完整的系统时,典型的拓扑结构有管道形、树形、星形等。设计者应该采用与问题结构相适应的、尽可能简单的拓扑结构,以减少子系统之间的交互数量。,典型应用系统的组织结构,使用面向对象方法开发软件时,在分析与设计之间并没有明确的分界线,对于问题域子系统来说,情况更是如此。但是,分析与设计毕竟是性质不同的两类开发工作,分析工作可以而且应该与具体实现无关,设计工作则在很大程度上受具体实现环境的约束。在开始进行设计工作之前(至少在完成设计之前),设计者应该了解本项目预计要使用的编程语言,可用的软构件库(主要是类库)以及程序员的编程经验。,设计问题域子系统,通过面向对象分析所得出的问题域精确模型,为设计问题域子系统奠定了良好的基础,建立了完整的框架。使用面向对象方法学开发软件,能够保持问题域组织框架的稳定性,从而便于追踪分析、设计和编程的结果。对于需求可能随时间变化的系统来说,稳定性是至关重要的。,1. 调整需求有两种情况会导致修改通过面向对象分析所确定的系统需求:一是用户需求或外部环境发生了变化;二是分析员对问题域理解不透彻或缺乏领域专家帮助,以致面向对象分析模型不能完整、准确地反映用户的真实需求。2. 重用已有的类代码重用从设计阶段开始,在研究面向对象分析结果时就应该寻找使用已有类的方法。若因为没有合适的类可以重用而确实需要创建新的类,则在设计这些新类的协议时,必须考虑到将来的可重用性。如果有可能重用已有的类,则重用已有类的典型过程如下:,(1) 选择有可能被重用的已有类,标出这些候选类中对本问题无用的属性和服务,尽量重用那些能使无用的属性和服务降到最低程度的类。(2) 在被重用的已有类和问题域类之间添加泛化关系(即从被重用的已有类派生出问题域类)。(3) 标出问题域类中从已有类继承来的属性和服务,现在已经无须在问题域类内定义它们了。(4) 修改与问题域类相关的关联,必要时改为与被重用的已有类相关的关联。,3. 把问题域类组合在一起在面向对象设计过程中,设计者往往通过引入一个根类而把问题域类组合在一起。事实上,这是在没有更先进的组合机制可用时才采用的一种组合方法。此外,这样的根类还可以用来建立协议。4. 增添一般化类以建立协议在设计过程中常常发现,一些具体类需要有一个公共的协议,也就是说,它们都需要定义一组类似的服务。在这种情况下可以引入一个附加类(例如,根类),以便建立这个协议(即命名公共服务集合,这些服务在具体类中仔细定义)。,5. 调整继承层次如果面向对象分析模型中包含了多重继承关系,然而所使用的程序设计语言却并不提供多重继承机制,则必须修改面向对象分析的结果。即使使用支持多重继承的语言,有时也会出于实现考虑而对面向对象分析结果作一些调整。下面分几种情况讨论:(1) 使用多重继承机制使用多重继承机制时,应该避免出现属性及服务的命名冲突。下面通过例子说明避免命名冲突的方法。,下图是一种多重继承模式的例子,这种模式可以称为窄菱形模式。,(2) 使用单继承机制如果打算使用仅提供单继承机制的语言实现系统,则必须把面向对象分析模型中的多重继承结构转换成单继承结构。示例如图所示。,6. ATM系统实例ATM系统的问题域子系统的结构:,在面向对象设计过程中,应该对系统的人机交互子系统进行详细设计,以确定人机交互的细节。人机交互部分的设计结果,将对用户情绪和工作效率产生重要影响。由于对人机界面的评价,在很大程度上由人的主观因素决定,因此,使用由原型支持的系统化的设计策略,是成功地设计人机交互子系统的关键。,设计人机交互子系统,1. 分类用户人机交互界面是给用户使用的,显然,为设计好人机交互子系统,设计者应该认真研究使用它的用户。应该深入到用户的工作现场,仔细观察用户是怎样做他们的工作的,这对设计好人机交互界面是非常必要的。为了更好地了解用户的需要与爱好,以便设计出符合用户需要的界面,设计者首先应该把将来可能与系统交互的用户分类。通常从下列几个不同角度进行分类:按技能水平分类(新手、初级、中级、高级)。按职务分类(总经理、经理、职员)。按所属集团分类(职员、顾客)。,2. 描述用户应该仔细了解将来使用系统的每类用户的情况,把获得的下列各项信息记录下来:用户类型。使用系统欲达到的目的。特征(年龄、性别、受教育程度、限制因素等)。关键的成功因素(需求、爱好、习惯等)。技能水平。完成本职工作的脚本。,3. 设计命令层次设计命令层次的工作通常包含以下几项内容:(1) 研究现有的人机交互含义和准则(2) 确定初始的命令层次所谓命令层次,实质上是用过程抽象机制组织起来的、可供选用的服务的表示形式。 (3) 精化命令层次应该考虑下列一些因素:次序整体-部分关系宽度和深度操作步骤,4. 设计人机交互类人机交互类与所使用的操作系统及编程语言密切相关。例如,在Windows环境下运行的Visual C+语言提供了MFC类库,设计人机交互类时,往往仅需从MFC类库中选出一些适用的类,然后从这些类派生出符合自己需要的类就可以了。,虽然从概念上说,不同对象可以并发地工作,但是,在实际系统中,许多对象之间往往存在相互依赖关系。此外,在实际使用的硬件中,可能仅由一个处理器支持多个对象。因此,设计工作的一项重要内容就是,确定哪些是必须同时动作的对象,哪些是相互排斥的对象。然后进一步设计任务管理子系统。,设计任务管理子系统,1. 分析并发性通过面向对象分析建立起来的动态模型,是分析并发性的主要依据。如果两个对象彼此间不存在交互,或者它们同时接受事件,则这两个对象在本质上是并发的。通过检查各个对象的状态图及它们之间交换的事件,能够把若干个非并发的对象归并到一条控制线中。所谓控制线,是一条遍及状态图集合的路径,在这条路径上每次只有一个对象是活动的。在计算机系统中用任务(task)实现控制线,一般认为任务是进程(process)的别名。通常把多个任务的并发执行称为多任务。,2. 设计任务管理子系统常见的任务有事件驱动型任务、时钟驱动型任务、优先任务、关键任务和协调任务等。设计任务管理子系统,包括确定各类任务并把任务分配给适当的硬件或软件去执行。(1) 确定事件驱动型任务(2) 确定时钟驱动型任务(3) 确定优先任务(4) 确定关键任务(5) 确定协调任务(6) 尽量减少任务数(7) 确定资源需求,数据管理子系统是系统存储或检索对象的基本设施,它建立在某种数据存储管理系统之上,并且隔离了数据存储管理模式(文件、关系数据库或面向对象数据库)的影响。,设计数据管理子系统,1)文件管理系统使用它长期保存数据具有成本低和简单等特点,但是,文件操作的级别低,为提供适当的抽象级别还必须编写额外的代码。此外,不同操作系统的文件管理系统往往有明显差异。2)关系数据库管理系统有下列一些主要优点:(1) 提供了各种最基本的数据管理功能。(2) 为多种应用提供了一致的接口。(3) 标准化的语言。,1.选择数据存储管理模式,有下列一些主要缺点:(1) 运行开销大(2) 不能满足高级应用的需求(3) 与程序设计语言的连接不自然3)面向对象数据库管理系统面向对象数据库管理系统是一种新技术,主要有两种设计途径: (1) 扩展的关系数据库管理系统(2) 扩展的面向对象程序设计语言,2.设计数据管理子系统,设计数据管理子系统,既需要设计数据格式又需要设计相应的服务。,1)设计数据格式设计数据格式的方法与所使用的数据存储管理模式密切相关,下面分别介绍适用于每种数据存储管理模式的设计方法:(1) 文件系统定义第一范式表为每个第一范式表定义一个文件。测量性能和需要的存储容量。修改原设计的第一范式,以满足性能和存储需求。必要时把泛化结构的属性压缩在单个文件中,以减少文件数量。,(2) 关系数据库管理系统定义第三范式表:列出每个类的属性表;把属性表规范成第三范式,从而得出第三范式表的定义。为每个第三范式表定义一个数据库表。测量性能和需要的存储容量。修改先前设计的第三范式,以满足性能和存储需求。(3) 面向对象数据库管理系统扩展的关系数据库途径:使用与关系数据库管理系统相同的方法。扩展的面向对象程序设计语言途径:不需要规范化属性的步骤,因为数据库管理系统本身具有把对象值映射成存储值的功能。,2)设计相应的服务如果某个类的对象需要存储起来,则在这个类中增加一个属性和服务,用于完成存储对象自身的工作。应该把为此目的增加的属性和服务作为“隐含”的属性和服务,即无须在面向对象设计模型的属性和服务层中显式地表示它们,仅需在关于类与对象的文档中描述它们。下面介绍使用不同数据存储管理模式时的设计要点。,(1) 文件系统被存储的对象需要知道打开哪个(些)文件,怎样把文件定位到正确的记录上,怎样检索出旧值(如果有的话),以及怎样用现有值更新它们。此外,还应该定义一个ObjectServer(对象服务器)类,并创建它的实例。该类提供下列服务:通知对象保存自身;检索已存储的对象(查找,读值,创建并初始化对象),以便把这些对象提供给其他子系统使用。注意,为提高性能应该批量处理访问文件的要求。,(2) 关系数据库管理系统被存储的对象,应该知道访问哪些数据库表,怎样访问所需要的行,怎样检索出旧值(如果有的话),以及怎样用现有值更新它们。此外,还应该定义一个ObjectServer类,并声明它的对象。该类提供下列服务:通知对象保存自身;检索已存储的对象(查找,读值,创建并初始化对象),以便由其他子系统使用这些对象。,(3) 面向对象数据库管理系统扩展的关系数据库途径:与使用关系数据库管理系统时方法相同。扩展的面向对象程序设计语言途径:无须增加服务,这种数据库管理系统已经给每个对象提供了“存储自己”的行为。只需给需要长期保存的对象加个标记,然后由面向对象数据库管理系统负责存储和恢复这类对象。,在ATM系统例子中,需要存储的对象主要是账户类的对象。为了支持数据管理子系统的实现,账户类对象必须知道自己是怎样存储的,有两种方法可以达到这个目的。(1) 每个对象自己保存自己账户类对象在接到“存储自己”的通知后,知道怎样把自身存储起来(需要增加一个属性和一个服务来定义上述行为)。(2) 由数据管理子系统负责存储对象,3.例子,账户类对象在接到“存储自己”的通知后,知道应该向数据管理子系统发送什么消息,以便由数据管理子系统把它的状态保存起来,为此也需要增加属性和服务来定义上述行为。使用这种方法的优点,是无须修改问题域子系统。应该定义一个数据管理类ObjectServer,并声明它的对象。这个类提供下列服务:通知对象保存自身或保存需长期存储的对象的状态;检索已存储的对象并使之“复活”。,需要综合考虑对象模型、动态模型和功能模型,才能正确确定类中应有的服务。状态图中状态转换所触发的动作,在功能模型中有时可能扩展成一张数据流图。数据流图中的某些处理可能与对象提供的服务相对应,下列规则有助于确定操作的目标对象:,设计类中的服务,1.确定设计类中应有的服务,(1) 如果某个处理的功能是从输入流中抽取一个值,则该输入流就是目标对象。(2) 如果某个处理具有类型相同的输入流和输出流,而且输出流实质上是输入流的另一种形式,则该输入输出流就是目标对象。(3) 如果某个处理从多个输入流得出输出值,则该处理是输出类中定义的一个服务。(4) 如果某个处理把对输入流处理的结果输出给数据存储或动作对象,则该数据存储或动作对象就是目标对象。,下面两条规则有助于确定处理的归属:(1) 如果处理影响或修改了一个对象,则最好把该处理与处理的目标(而不是触发者)联系在一起。(2) 考察处理涉及的对象类及这些类之间的关联,从中找出处于中心地位的类。如果其他类和关联围绕这个中心类构成星形,则这个中心类就是处理的目标。,在面向对象设计过程中还应该进一步设计实现服务的方法,主要应该完成以下几项工作。1)设计实现服务的算法设计实现服务的算法时,应该考虑下列几个因素:(1) 算法复杂度。(2) 容易理解与容易实现。 (3) 易修改。2)选择数据结构在分析阶段,仅需考虑系统中需要的信息的逻辑结构,在面向对象设计过程中,则需要选择能够方便、有效地实现算法的物理数据结构。,2.设计实现服务的方法,3)定义内部类和内部操作在面向对象设计过程中,可能需要增添一些在需求陈述中没有提到的类,这些新增加的类,主要用来存放在执行算法过程中所得出的某些中间结果。此外,复杂操作往往可以用简单对象上的更低层操作来定义。因此,在分解高层操作时常常引入新的低层操作。在面向对象设计过程中应该定义这些新增加的低层操作。,在对象模型中,关联是联结不同对象的纽带,它指定了对象相互间的访问路径。在面向对象设计过程中,设计人员必须确定实现关联的具体策略。既可以选定一个全局性的策略统一实现所有关联,也可以分别为每个关联选择具体的实现策略,以与它在应用系统中的使用方式相适应。为了更好地设计实现关联的途径,首先应该分析使用关联的方式。,设计关联,1. 关联的遍历在应用系统中,使用关联有两种可能的方式:单向遍历和双向遍历。在应用系统中,某些关联只需要单向遍历,这种单向关联实现起来比较简单,另外一些关联可能需要双向遍历,双向关联实现起来稍微麻烦一些。在使用原型法开发软件的时候,原型中所有关联都应该是双向的,以便于增加新的行为,快速地扩充和修改原型。,2. 实现单向关联用指针可以方便地实现单向关联。,3. 实现双向关联许多关联都需要双向遍历,当然,两个方向遍历的频度往往并不相同。实现双向关联有下列3种方法:,(1) 只用属性实现一个方向的关联,当需要反向遍历时就执行一次正向查找。(2) 两个方向的关联都用属性实现。,(3) 用独立的关联对象实现双向关联。,4. 关联对象的实现,可以引入一个关联类来保存描述关联性质的信息,关联中的每个连接对应着关联类的一个对象。实现关联对象的方法取决于关联的重数。对于一对一关联来说,关联对象可以与参与关联的任一个对象合并。对于一对多关联来说,关联对象可以与“多”端对象合并。如果是多对多关联,则关联链的性质不可能只与一个参与关联的对象有关,通常用一个独立的关联类来保存描述关联性质的信息,这个类的每个实例表示一条具体的关联链及该链的属性。,系统的各项质量指标并不是同等重要的,设计人员必须确定各项质量指标的相对重要性(即确定优先级),以便在优化设计时制定折衷方案。系统的整体质量与设计人员所制定的折衷方案密切相关。最终产品成功与否,在很大程度上取决于是否选择好了系统目标。在折衷方案中设置的优先级应该是模糊的。最常见的情况,是在效率和清晰性之间寻求适当的折衷方案。,设计优化,1.确定优先级,1)增加冗余关联以提高访问效率在面向对象分析过程中,应该避免在对象模型中存在冗余的关联。但是,在面向对象设计过程中,应当考虑用户的访问模式,及不同类型的访问彼此间的依赖关系时,就会发现,分析阶段确定的关联可能并没有构成效率最高的访问路径。下面用设计公司雇员技能数据库的例子,说明分析访问路径及提高访问效率的方法。下图是从面向对象分析模型中摘取的一部分。公司类中的服务find_skill返回具有指定技能的雇员集合。例如,用户可能询问公司中会讲日语的雇员有哪些人。,2.提高效率的几项技术,假设某公司共有2000名雇员,平均每名雇员会10种技能,则简单的嵌套查询将遍历雇员对象2000次,针对每名雇员平均再遍历技能对象10次。如果全公司仅有5名雇员精通日语,则查询命中率仅有1/4000。,公司、雇员及技能之间的关联链,提高访问效率的一种方法是使用哈希(Hash)表。但是,当仅有极少数对象满足查询条件时,查询命中率仍然很低。在这种情况下,更有效的提高查询效率的改进方法是,给那些需要经常查询的对象建立索引。例如,针对上述例子,可以增加一个额外的限定关联“精通语言”,用来联系公司与雇员这两类对象,如下图:,为雇员技能数据库建立索引,2)调整查询次序改进了对象模型的结构,从而优化了常用的遍历之后,接下来就应该优化算法了。优化算法的一个途径是尽量缩小查找范围。例如,假设用户在使用上述的雇员技能数据库的过程中,希望找出既会讲日语又会讲法语的所有雇员。如果某公司只有5位雇员会讲日语,会讲法语的雇员却有200人,则应该先查找会讲日语的雇员,然后再从这些会讲日语的雇员中查找同时又会讲法语的人。,3)保留派生属性通过某种运算而从其他数据派生出来的数据,是一种冗余数据。通常把这类数据“存储”(或称为“隐藏”)在计算它的表达式中。如果希望避免重复计算复杂表达式所带来的开销,可以把这类冗余数据作为派生属性保存起来。派生属性既可以在原有类中定义,也可以定义新类,并用新类的对象保存它们。每当修改了基本对象之后,所有依赖于它的、保存派生属性的对象也必须相应地修改。,建立良好的类继承是非常重要的。利用类继承能够把若干个类组织成一个逻辑结构。与建立类继承有关的问题有:1)抽象与具体2)为提高继承程度而修改类定义3)利用委托实现行为共享仅当存在真实的一般-特殊关系(即子类确实是父类的一种特殊形式)时,利用继承机制实现行为共享才是合理的。如果你只想把继承作为实现操作共享的一种手段,则利用委托(即把一类对象作为另一类对象的属性,从而在两类对象间建立组合关系)也可以达到同样目的,而且这种方法更安全。,3.调整继承关系,用表实现栈的两种方法,