- 1.38 MB
- 2022-07-30 发布
- 1、本文档由用户上传,淘文库整理发布,可阅读全部内容。
- 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,请立即联系网站客服。
- 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细阅读内容确认后进行付费下载。
- 网站客服QQ:403074932
在开始设计或实现之前试图定义大多数需求?(错)在编程和测试之前定义和提交完整的架构。(错)UP中,所有开发活动和制品可选,根据特定问题和需要选择制品。(对)UP和瀑布模型不同,不是在开始就定义全部需求。(对)初始阶段不是需求阶段,而是研究可行性的阶段,要进行充分的调查以确定继续或终止项目。(对)细化阶段也不是需求或设计阶段,而是迭代地实现核心架构并解决高风险问题的阶段。(对)UP是迭代和不断进化的,所有实现前的需求和设计是不完整的。(对)对整个项目不应有详细的计划。应该制定估计结束日期和主要里程碑的阶段计划,但是不要对这些里程碑详细定义细粒度的步骤。只能预先对一个迭代制定更为详细的迭代计划。详细计划是由一次次迭代的调整而完成的。(对)不要单独建模,而是结对(或三个人)在白板上建模,同时记住建模的目的是发现、理解和共享大家的理解。(对)采用敏捷开发并不意味着不用建模。(对)不要对所有或大多数软件设计建模或应用UML。只需要对设计空间中不常见、困难和棘手的一小部分问题建模和应用UML。(对)大部分迭代方法建议迭代时间在2-6周之内。小步骤、快速反馈和调整是迭代开发的主要思想,时间过长会增加风险。(对)迭代的输出不是实验性的或将丢弃的原型,迭代开发也不是构造原型,其输出是最终系统的产品子集。(对)用例部分会使用一些UML用例图,但绝不会引入大量图形。初始阶段,主要以文字方式表达需求。(对)初始阶段定义大部分需求。(错)期望初始阶段的预算和计划是可靠的。(错)定义架构(应该在细化阶段以迭代方式定义架构)。(错)认为正确的工作顺序应该是:定义需求,设计架构,实现。(错)没有业务案例或设想制品。(错)详细编写所有用例。(错)没有详细编写任何用例。与之相反,应该详细编写10%-20%的用例以便获得对问题范围的真实认知。(对)用例描述了从参与者(Actor)角度看系统(黑盒子)做了什么WHAT。(对)用例是文本形式的情节描述,用以说明某参与者使用系统以实现某些目标。(对)用例是文本文档,而非图形;用例建模主要是编写文本的活动,而非制图。(对)用例主要是说明系统如何工作的功能性或行为性需求。(对)用例中,一个用户可以充当多种角色。(对)主成功场景:典型的、无条件的、理想方式的成功场景扩展:成功或失败的替代场景用例之重在于编写文本,用例图和用例关系在编写用例工作中是次要的。(对)世界级用例专家都对用例图和用例关系不予重视,而是着重于编写文本。(对)初始阶段并是不要以向详细形式编写用例。(对)细化阶段结束时,详细编写了80-90%的用例。(对)构造阶段编写用例,在这个阶段可能涉及编写一些次要的用例,也可能举办需求讨论会,但是次数大大少于细化阶段。(对)应该早在完整地分析和记录大多数需求之前,尽早进行具有产品品质的编程和测试。(对)通常在若干迭代内对同一用例的不同场景进行开发,渐进的扩充系统直到最终完成所有需要的功能。(对)\n细化不是设计阶段,不是要完成所有模型的开发。(对)细化不是要创建可以丢弃的原型,所产生的代码应该是最终系统的产品化子集。(对)细化阶段没有处理具有风险的元素和核心架构。(错)认为细化阶段是进行概念验证编程的阶段,而不是对产品核心架构编程的阶段。(错)避免瀑布思维倾向,为完成详尽或正确的领域模型而进行大量建模工作。这些方式都应避免,并且这种过量的建模工作反而会导致分析停滞,这种调查几乎不会有什么回报。(对)领域模型是对所关注的现实世界领域中事物的可视化,而不是诸如java或C#类的软件对象,或有职责软件对象。以下元素不适用于领域模型:软件制品,例如窗口或数据库、职责或方法。库存、金融、卫生等很多领域都存在已经发布的、绘制精细的领域模型和数据模型。以此为基础修改为领域模型。(对)领域模型是从概念角度出发,是否需要记录关联,基于现实世界的需要,而不是基于软件的需要,尽管在实现过程中,会出现大量对关联的需要。(对)领域模型关联表示中,阅读导向箭头对模型不具有特别意义,只是对阅读图的人有所帮助。(对)关联命名中,以“类名-动词短语-类名”的格式为关联命名,其中的动词短语构成了可读的和意义的顺序。(对)关联多重性的值表示在特定的时刻(而不是在某个时间跨度内)有效关联的实例数量。(对)没有唯一正确的领域模型。(对)用例文本及其表示的系统事件是创建SSD的输入。(对)SSD中的操作可以在操作契约中进行分析,在词汇表中被详细描述,并且作为设计协作对象的起点。(对)为所有系统操作产生完整详细的后置条件集合是不可能的,或是没必要的。初始:初始阶段不会引人契约,因为过于详细。细化:如果使用契约的话,大部分契约将在细化阶段编写,这时已经编写了大部分的用例,只对最复杂和微妙的系统操作编写契约。尽早编程、测试和演示有助于尽早引发不可避免的变更。UML包图也可作为软件架构文档中的视图,其主要输入是补充性规格说明中记录的架构方面的约束和要点。敏捷构建静态模型和动态模型提倡并行创建模型:花费较短的时间创建交互图(动态),然后转到对应的类图(静态),交替进行。通信图中,一般不为第一个消息使用顺序编号。RDD中,认为软件对象具有职责,即对其所作所为的抽象。对于软件领域对象来说,由于领域模型描述了领域对象的属性和关联,因此其通常产生与认知相关的职责。在绘制UML交互图时,就是在决定职责的分配。绘制UML交互图以及编写代码时,就可以运用GRASP原则了。对于用例中一系列特定事件,SSD展示了直接与系统交互的外部参与者,系统作为黑盒以及由参与者发起的系统事件。SSD由用例导出,若用例很清楚,可以不用画SSD,可以以用例名命名SSD。不用为所有场景创建SSD。(对)初始:不会引入SSD,除非对所涉及的技术进行估算。细化:大部分SSD在此阶段完成。有利于系统事件的细节以便明确系统必须设计和处理的操作,有利于编写操作契约,有利于估算的支持。组合聚集部分,容器容纳内容,记录者进行记录,封装的容器或记录器是创建其容纳或记录的事物很好的候选者。\n对稳定的元素和普遍的元素的高耦合一般不是一个问题。一个JavaJ2EE应用对Java库(java.util,等等)的耦合没有问题,因为它们是稳定的,并被普遍使用。不要花费太多时间到“未来验证”的或没有实际理由的低耦合设计上。对于同一用例场景的所有系统事件使用相同的控制器类。为了使发送者对象能够向接收者对象发送消息,发送者必须具有接收者的可见性,即发送者必须拥有对接收者对象的某种引用或指针。不要测试对象的类型,也不要使用条件逻辑来执行基于类型的不同选择。UP项目将其工作和迭代组织为四个主要阶段:w初始(Inception):大体上的构想、业务案例、范围和模糊评估——可行性研究。w细化(Elaboration):已精化的构想、核心架构的迭代实现、高风险的解决、确定大多数需求和范围以及进行更为实际的评估。w构造(Construction):对遗留下来的风险较低和比较简单的元素进行迭代实现,准备部署。w移交(Transition)进行beta测试和部署。UP核心思想:§短时间定量迭代、进化和可适应性开发。§UP中:在早期迭代中解决高风险和高价值的问题。§不断地让用户参与评估、反馈和需求。§在早期迭代中建立内聚的核心架构。§不断地验证质量;提早、经常和实际地测试。§实行变更请求和配置管理。迭代的一个关键思想是时间定量或时长固定。约定了时间,不许按时完成,实在完不成,不能推迟时间,而是剔除一些任务或需求。早期迭代远离系统的“真实路径”。通过反馈和调整,系统向最适宜的需求和设计收敛。在后期迭代中,很少会在需求上产生显著变化,但是存在这种可能性。这种后期的变化可能会给组织带来业务竞争优势。如何在迭代项目中处理变更w一方面认同和稳定一组需求,另一方面接受需求不断变更的事实。w每次迭代选择一小组需求,快速设计、实现和测试。w早期迭代可能并不准确,但是快速实施可以得到快速反馈----来自用户、开发人员和测试人员的反馈。w早期迭代中系统偏离正确轨迹的程度会大于后继迭代。随着时间的发展,系统将会收敛。w最好及早解决和验证具有风险的、关键的设计决策。初始阶段要解决的问题:涉众是否就项目设想基本达成一致;项目是否值得继续进行认真研究?初始阶段会创建的制品§设想和业务用例(VisionandBusinessCase)描述高阶目标与约束、业务案例,并提供执行摘要。§用例模型(Use-CaseModel)\n描述功能需求。在初始阶段,确定大部分用例名称,详细分析10%的用例。§补充性规格说明(SupplementarySpecification)描述其他需求,主要是非功能性需求。初始阶段,多考虑关键的非功能性需求,其对架构将会产生主要影响。§词汇表(Glossary)关键领域术语和数据字典。§风险列表和风险管理计划(RiskList&RiskManagementPlan)描述风险(业务、技术、资源和进度)及应对和缓解的方法。§原型和概念验证(PrototypesandProof-of-concepts)澄清设想,验证技术思路。§迭代计划(IterationPlan)描述第一个细化迭代的任务。§阶段计划和软件开发计划(PhasePlan&SoftwareDevelopmentPlan)对细化阶段的持续时间和工作量进行粗略估计。工具、人员、教育和其他资源。§开发案例(DevelopmentCase)就待定项目,对UP步骤和制品进行定制的描述。在UP中,通常会为特定项目进行定制。关键的UP需求制品§用例模型-一组使用系统的典型场景。主要用于功能(行为的)需求。§补充规格说明-基本上是用例之外的所有内容。主要用于所有非功能需求,例如性能或许可发布。该制品也用来记录没有表示(或不能表示)为用例的功能特性,例如报表生成。§词汇表-定义重要的术语,数据字典记录了关于数据的需求,例如有效性规则,容许值等。对象属性、操作调用的参数、报表布局等。§设想-概括了高阶需求,这些需求在用例模型和补充性规格说明中进行细化。设想也概括了项目的业务案例。设想是简短的执行概要文档,用以快速了解项目的主要思想。§业务规则-领域规则,描述了凌驾于某一软件项目的需求或政策,这些规则是领域或业务所要求的,并且许多应用应该遵从这些规则。例如政府的税收法规。§领域规则的细节可以记录在补充性规格说明中,因为这些规则通常更为持久,对不止一个软件项目适用,应将其放入集中的业务规则制品,以便重用。有三种外部参与者:§主要参与者:具有用户目标,并通过使用SuD的服务完成。通常用来发现驱动用例的用户目标。§协助参与者:为SuD提供服务(例如,信息服务)。自动付费授权服务即是一例。协助参与者通常是计算机系统,但也可以是组织或人。协助参与者通常是为了明确外部接口和协议。§为何确定协助参阅者?为了明确外部接口或利益。§幕后参与者:在用例行为中具有影响或利益,但不是主要或协助参与者。例如,政府收税机构。通常是为了确保确定并满足所有必要的重要事物。如果不明确地对幕后参与者进行命名,则有时很容易忽略其影响或利益。不同形式化程度或格式编写用例§摘要--简洁的一段式概要,通常用于主成功场景。何时使用在早期需求分析过程中,为快速了解主体和范围使用。可能只需要几分钟编写。§非正式--非正式的段落格式。用几个段落覆盖不同场景。何时使用?同上。\n§详述--详细编写所有步骤及各种变化,同时具有补充部分,如前置条件和成功保证。何时使用?确定并以摘要形式编写了大量用例后,在第一次需求讨论会中,详细地编写其中少量的具有重要架构和高价值的用例。用例描述最为广泛的格式(alistair.cockburn.us上的模板):w用例名称:以动词开始w范围:界定了所要设计的系统w级别:用户目标级别或子功能级别(重用,如信用卡支付)。w主要参与者:调用系统,使之交付服务w涉众及其关注点列表:关注该用例的人及其需要。重要!能够让我们更清楚详细的系统职责w前置条件:值得告知读者的,开始前必须为真的条件w成功保证:值得告知读者的,成功完成必须满足的条件w主成功场景:典型的、无条件的、理想方式的成功场景w扩展:成功或失败的替代场景w特殊需求:相关的非功能需求w技术和数据变元表:不同的I/O方法和数据格式w发生频率:影响对实现的调查、测试和时间安排w杂项:例如未解决问题。场景记录以下三种步骤:1)参与者之间的交互。2)确认过程(通常由系统完成)。3)系统完成的状态变更(例如,记录或更改某事物)如果想描述任何步骤都可能发生的扩展条件,标识*a,*b。以无用户界面的本质风格编写用例w收银员会说“登录”。w收银员想到的图形界面、对话框、用户名、密码。w这是实现的一种机制,而不是目标本身。w与实现机制无关的目标:“标识自己的身份并得到认证”。w或更高层次的目标:“防盗”。以本质风格编写用例w以本质风格编写用例,摒除用户界面并且关注参与者的意图。w具体风格--用例文本涵盖对用户界面的决策。在早期需求工作中应该避免。假设在管理用户用例中需要标识身份和认证本质风格1.管理员标识自己的身份2.系统对此身份进行验证3……具体风格1.管理员在对话框中输入ID和口令\n2.系统对管理员进行验证3.系统显示“编辑用户”界面4.……编写黑盒用例,不对系统内部工作、构件或设计进行描述,通过职责描述系统。黑盒风格:系统记录销售非黑盒风格:1.系统将销售信息写入数据库。2.系统对销售信息生成SQLINSERT语句。可以利用测试发现有用的用例,经验方法l老板测试lEBP测试l规模测试EBP(ElementaryBusinessProcess)即基本业务过程,定义如下:一个人于某个时刻在一个地点所执行的行为,用以响应业务事件。该任务能够增加可量化的价值,并且以持久状态留下数据。用例图是模型图,用例图可包含用例,活动者以及它们之间的关系,这些关系可以是:Øinclude(包含)Øextend(扩展)Øgeneralization(泛化)什么样的问题有助于寻找参与者和目标:w谁来启动和停止系统。w谁来完成用户管理和安全管理。w谁来完成系统管理。w“时间”是管理者吗。因为系统要响应时间事件而完成某些活动。w系统失败时,是否存在监控进程将系统重新启动。w软件升级是如何处理的,是推模式还是拉模式。w除了人作为主要参与者外,还有其他外部的软件或自动机器系统调用该系统的服务吗。w谁来考察系统活动或性能。w谁来考察日志,是否可以远程检索。w系统发生错误或故障时应通知谁。设想中的元素包括:w修订历史。w定位。w涉众描述。w产品概览。w系统特性概要。w其它需求和约束。细化阶段,先写设想还是用例\n建议如下顺序:w首先编写简要的设想草案。w确定用户目标和对应的用例名称。w详细编写一些用例,并且开始编写补充性规格说明。w精化设想,对以上制品信息进行概括。细化阶段是一般项目最初的一系列迭代,其中包括:Ø对核心、有风险的软件架构进行编程和测试。Ø发现并稳定需求的主体部分。Ø规避主要风险。细化阶段开始构建的制品:领域模型、设计模型、软件架构文档、数据模型、用例示意板、用户界面原型。领域模型是对领域内的概念类或现实世界中对象的可视化表示,而不是软件对象的表示。领域模型用一套类图来表示,这些类没有操作。它可以显示:l领域对象或者概念类l概念类之间的关联l概念类的属性报表对象—领域模型中是否要包括“票据”?以下是一些要考虑的因素:§一般来说,在领域模型中显示其它信息的报表并没有意义,因为其所有信息都是源于或者复制于其它信息源的。§另外一方面,就业务规则而言,收据又有特殊的作用,在我们退货时,我们需要收据作为凭据。何时需要描述类§需要有关商品或服务的描述,独立于任何商品或服务的现有实例。§删除其所描述事务(如Item)的实例后,导致信息丢失,而这些信息是需要维护的,但是被错误地与所删除的事务关联起来。§减少冗余或重复信息。什么是系统顺序图§是为阐述与所讨论系统相关的输入和输出事件而快速、简单地创建的制品。§它展示了对一个特定的用例,直接与系统交互的外部参与者、系统(作为黑盒)以及由参与者发起的系统事件。应为每个用例的主成功场景,以及频繁发生的或者复杂的替代场景绘制SSD。SSD中,软件系统要对以下三种事件进行响应:1.来自于参与者(人或计算机)的外部事件。2.时间事件。3.错误或异常(通常源于外部)。操作契约采用前置条件和后置条件的形式,描述领域模型里对象的详细变化,并作为系统操作的结果。操作契约为用例指出的系统操作的效用提供了更详细的分析。§契约的主要输入是SSD中确定的系统操作、领域模型和领域专家的见解。\n§契约可作为对象设计的输入,因为描述的变化可能是软件对象或数据库所需要的。后置条件描述了领域模型中对象状态的变化.包括:w实例创建和删除。w属性值的变化。w关联形成和消除。模型-视图分离原则§不要将非UI对象直接与UI对象连接或耦合。因为窗口与某个应用相关,非窗口对象可以重用。§不要在UI对象方法中加入应用逻辑(例如税金计算)。UI对象只初始UI元素,接收UI事件,将应用逻辑的请求委托给非UI对象(如领域对象)。绘制UML对象图时,要回答以下关键问题:w对象的职责是什么;w对象在与谁协作;w应该采用什么设计模式。publicclassA{privateBmyB=newB();publicvoiddoOne(){myB.doTwo();myB.doThree();}//…}\npublicclassSale{privatePaymentpayment;publicvoidmakePayment(MoneycashTendered){payment=newPayment(cashTendered);//…}//…}交互图中,消息表达式的基本语法return=message(parameter:parameterType):returnType创始消息w最开始的消息在UML称为创始消息(FoundMessage),以实心圆作为起点表示此类消息。w创始消息表示没有特定发送者、发送者不明确或消息源众多的消息。主动类:w主动对象(activeobject)运行于自己控制的执行线程之上。w主动对象的类即为主动类对象设计需要输入哪些制品,他们与对象设计有什么样的关系。对象的行为职责w自身执行一些行为,例如创建对象或计算。w初始化其他对象中的动作。w控制或者协调其它对象的活动。\n对象的认知职责w对私有封装数据的认知。w对相关对象的认知。w对其能够导出或计算的事物的认知。设计原则名称设计原则简介单一职责原则类的职责要单一,不能将太多的职责放在一个类中开闭原则软件实体对扩展是开放的,但对修改是关闭的,即在不修改一个软件实体的基础上去扩展其功能。里氏代换原则在软件系统中,一个可以接受基类对象的地方必然可以接受一个子类对象依赖倒转原则要针对抽象层编程,而不要针对具体类编程接口隔离原则使用多个专门的接口来取代一个统一的接口合成复用原则在系统中应该尽量多使用组合和聚合关联关系,尽量少使用甚至不使用继承关系迪米特法则一个软件实体对其他实体的引用越少越好,或者说如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互l开闭原则实例l实例说明l某图形界面系统提供了各种不同形状的按钮,客户端代码可针对这些按钮进行编程,用户可能会改变需求要求使用不同的按钮,原始设计方案如图所示:\nl现对该系统进行重构,使之满足开闭原则的要求。l里氏代换原则实例l某系统需要实现对重要数据(如用户密码)的加密处理,在数据操作类(DataOperator)中需要调用加密类中定义的加密算法,系统提供了两个不同的加密类,CipherA和CipherB,它们实现不同的加密方法,在DataOperator中可以选择其中的一个实现加密操作。l实例说明l如果需要更换一个加密算法类或者增加并使用一个新的加密算法类,如将CipherA改为CipherB,则需要修改客户类Client和数据操作类DataOperator的源代码,违背了开闭原则。\nl现使用里氏代换原则对其进行重构,使得系统可以灵活扩展,符合开闭原则。l依赖倒转原则实例l实例说明l某系统提供一个数据转换模块,可以将来自不同数据源的数据转换成多种格式,如可以转换来自数据库的数据(DatabaseSource)、也可以转换来自文本文件的数据(TextSource),转换后的格式可以是XML文件(XMLTransformer)、也可以是XLS文件(XLSTransformer)等。l实例说明l由于需求的变化,该系统可能需要增加新的数据源或者新的文件格式,每增加一个新的类型的数据源或者新的类型的文件格式,客户类MainClass都需要修改源代码,以便使用新的类,但违背了开闭原则。现使用依赖倒转原则对其进行重构。\nl接口隔离原则实例l实例说明l下图展示了一个拥有多个客户类的系统,在系统中定义了一个巨大的接口(胖接口)AbstractService来服务所有的客户类。可以使用接口隔离原则对其进行重构。在迪米特法则中,对于一个对象,其朋友包括以下几类:(1)当前对象本身(this);(2)以参数形式传入到当前对象方法中的对象;(3)当前对象的成员对象;(4)如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;(5)当前对象所创建的对象。l迪米特法则实例l实例说明l\n某系统界面类(如Form1、Form2等类)与数据访问类(如DAO1、DAO2等类)之间的调用关系较为复杂,如图所示:将创建类A的实例的责任分配给类B,如果一个或多个下面的条件为真(越多越好):lB聚合了(aggregates)A对象。lB包含了(contains)A对象。lB记录了(records)A对象的实例。lB密切使用(closelyuses)A对象。lB拥有传递给创建A所需要的初始化数据(因此B是创建A的专家)。lB是对象A的创建者。在POS应用,谁需要负责创建SalesLineItem(条目)实例呢?\n部分领域模型wsale包含了(聚集)许多SalesLineItem对象,所以是良好候选者。产生了如下的对象交互设计。w这项职责分配的要求在Sale中定义MakeLineItem方法。lNextGENPOS应用,某个类需要知道销售总额。l谁负责了解销售总额?部分领域模型确定总额需要哪些信息?l销售的所有SalesLineItem实例及其小计之和。l\nSale实例包含了上述信息,根据信息专家建议,Sale是适合这一职责的对象类,是适合这项工作的信息专家。l给对象分配职责。为了确定商品的小计,需要哪些信息?答案:SalesLineItem.quantity、ProcuctionDescription.price。SalesLineItem知道其数量和与其关联的ProcuctionDescription。应该由SaleLineItem确定小计,他就是信息专家。Sale应当向每个SaleLineItem发送getSubtotal消息,并对其得到的结果求和。l为了实现获知并回答小计的职责,SaleLineItem必须知道产品价格。lProductDescription是回答价格的信息专家,因此SaleLineItem向他发送询问产品价格的消息。三个对象的设计类分配了如下职责:设计类职责\nSale知道销售的总额SalesLineItem知道商品的小计ProductSpecification知道产品的价格外观控制器l它代表了整个系统,设备或一个子系统。l它提供了从UI层往其他层的服务调用的主要入口l对整个物理单元的抽象,例如Register,TelecommSwitch,Phone或Robotl代表了整个软件系统的类,例如POSSysteml设计者选择用来表示整个系统,子系统的其他概念,例如如果是一个游戏软件,选择ChessGame。l什么时候选择外观控制器?l当没有“过多”的系统事件,或者UI不能把系统事件消息重定向到其他控制器(如在消息处理系统中)时,选择外观控制器是合适的。用例控制器l对每一个用例设置一个单独的控制器。l这是支持系统的人工造物。l什么时候选择用例控制器?当有太多的系统事件并设计不同的过程,用例控制器是一个好的选择。它将处理它们的任务分配给那些可管理的单独的类,也提供了一个获知和推理目前进行中的场景的当前状态的基础。“浮肿的”控制器(BloatedControllers)l如果设计得不合理,控制类内聚性不强-不聚焦并处理了太多领域的责任。l症兆l一个控制类接收所有的系统事件。l控制类自己处理了完成系统事件所需要的太多任务。l控制器有太多的属性并维持了系统或领域的信息。l解决办法l增加控制器(使用用例控制器,非外观控制器)。l设计控制器:把职责委派给其他对象。实现对象A到对象B的可见性通常有四种方式:w属性可见性AttributeVisibility:B是A的属性。w参数可见性Parametervisibility:B是A方法中的参数。w局部可见性LocalVisibility:B是A中方法的局部对象(不是参数)。w全局可见性GlobalVisibility:B具有某种方式的全局可见性。多态w问题:§如何处理基于类型的选择?•“If-then-else”;“select-case”?•很难方便地扩展有新变化的程序§如何创建可插拔的软件构件?•\n客户-服务器关系中的可视化构件,如何才能够替换服务器构件,而不对客户端产生影响呢?w解决方案§当相关选择或行为随类型(类)有所不同时,使用多态操作为变化的行为类型分配职责。多态示例1wNextGen问题:如何支持第三方税金计算器?§它们具有不同技术实现的不同的接口ØTCPsocketØSOAPinterfaceØJavaRMIinterface§基于多态,应该为不同的计算器(或计算器适配器)对象自身分配适配的职责,这可以通过多态的getTaxes操作来实现。纯虚构(PureFabrication)w问题:§面向对象设计依据真实世界中的概念来表示软件类§但是软件并非真实的世界§我们需要通过领域层对象来克服•低内聚或者耦合•低复用解决方案w对人为制造的类分配一组高内聚的职责,该类并不代表问题领域的概念-虚构的事物,用以支持高内聚、低耦合和复用。间接性(Indirection)w问题:§为了避免两个或多个事物之间的直接耦合,应该如何分配职责?§如何使对象解耦,以支持低耦合并提高复用性?w解决方案:§将职责分配给中介对象,使其作为其他构件或服务之间的媒介,以避免它们之间的直接耦合。防止变异(ProtectedVariations:PV)w问题:如何设计对象,子系统和系统,使其内部的变化或不稳定性不会对其它元素造成不良影响w解决方案:识别预计变化或不稳定之处,分配职责用以在这些变化之外创建稳定接口工厂方法模式(FactoryMethodPattern)又称为工厂模式,也叫虚拟构造器(VirtualConstructor)模式或者多态工厂(PolymorphicFactory)\n模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。ü实例二:日志记录器ü某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等,且用户可以根据要求动态选择日志记录方式,现使用工厂方法模式设计该系统。建造者模式(BuilderPattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。根据中文翻译的不同,建造者模式又可以称为生成器模式。实例:KFC套餐建造者模式可以用于描述KFC如何创建套餐:套餐是一个复杂对象,它一般包含主食(如汉堡、鸡肉卷等)和饮料(如果汁、可乐等)等组成部分,不同的套餐有不同的组成部分,而KFC的服务员可以根据顾客的要求,一步一步装配这些组成部分,构造一份完整的套餐,然后返回给顾客。\n适配器模式(AdapterPattern):将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。实例二:加密适配器ü某系统需要提供一个加密模块,将用户信息(如密码等机密信息)加密之后再存储在数据库中,系统已经定义好了数据库操作类。为了提高开发效率,现需要重用已有的加密算法,这些算法封装在一些由第三方提供的类中,有些甚至没有源代码。使用适配器模式设计该加密模块,实现在不修改现有类的基础上重用第三方加密方法。\n桥接模式(BridgePattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(HandleandBody)模式或接口(Interface)模式。实例二:跨平台视频播放器ü如果需要开发一个跨平台视频播放器,可以在不同操作系统平台(如Windows、Linux、Unix等)上播放多种格式的视频文件,常见的视频格式包括MPEG、RMVB、AVI、WMV等。现使用桥接模式设计该播放器。