教学课件第八讲设计模式

上传人:hs****ma 文档编号:568619644 上传时间:2024-07-25 格式:PPT 页数:70 大小:1.98MB
返回 下载 相关 举报
教学课件第八讲设计模式_第1页
第1页 / 共70页
教学课件第八讲设计模式_第2页
第2页 / 共70页
教学课件第八讲设计模式_第3页
第3页 / 共70页
教学课件第八讲设计模式_第4页
第4页 / 共70页
教学课件第八讲设计模式_第5页
第5页 / 共70页
点击查看更多>>
资源描述

《教学课件第八讲设计模式》由会员分享,可在线阅读,更多相关《教学课件第八讲设计模式(70页珍藏版)》请在金锄头文库上搜索。

1、第八讲第八讲 设计模式设计模式1设计模式概念与特点l设计模式概念l设计模式是一些面向对象的软件开发经验总结。一个设计模式有系统的命名、解释和评价,是某个重要的可重现的面向对象的设计方案。l设计模式特点l设计模式是被发现而不是被发明出来的。l设计模式是解决一类相关问题的通用技术。2设计模式组成l构造式构造式设计模式模式l结构式构式设计模式模式l行行为式式设计模式模式4设计模式描述方法设计模式描述方法广泛采用的设计模式描述是广泛采用的设计模式描述是 Erich Gamma Erich Gamma 等人采用的方式:等人采用的方式: 模式分类和名称:名称及一个简短摘要模式分类和名称:名称及一个简短摘要

2、 目的:设计用途、基本原理和目标,针对的特殊问题目的:设计用途、基本原理和目标,针对的特殊问题 别名:不同专家给予的命名别名:不同专家给予的命名 动机:描述设计问题的方案,其中类与对象的结构动机:描述设计问题的方案,其中类与对象的结构 应用:应用的条件,如何识别这些情况应用:应用的条件,如何识别这些情况 结构:用对象模型技术对模式进行结构表示,对象图、合作图等结构:用对象模型技术对模式进行结构表示,对象图、合作图等 成分:组成模式的类和对象,以及它们的职责成分:组成模式的类和对象,以及它们的职责 合作:成分之间如何合作实现它们的任务合作:成分之间如何合作实现它们的任务 效果:使用的利弊权衡,进

3、行必要改造的可能性和途径效果:使用的利弊权衡,进行必要改造的可能性和途径 实现:实现过程应注意的问题和技术,与程序语言的相关性实现:实现过程应注意的问题和技术,与程序语言的相关性 代码示例:用代码示例:用C+C+语言实现的代码和说明语言实现的代码和说明 已有的应用:应用实例介绍已有的应用:应用实例介绍 相关的模式:与之相关的其它模式相关的模式:与之相关的其它模式5设计模式的类型 设计模式设计模式 简要说明简要说明抽象工厂抽象工厂(Abstract Factory)(Abstract Factory)提供创建相关的一组对象的接口,不需要指定它们的具提供创建相关的一组对象的接口,不需要指定它们的具

4、体实现体实现构造器构造器(Builder)(Builder)将对象的结构与它的表示分离,可用同样的结构得到不将对象的结构与它的表示分离,可用同样的结构得到不同的表示同的表示工厂方法工厂方法(Factory Method)(Factory Method)定义创建对象的接口,但由子类来决定实例化定义创建对象的接口,但由子类来决定实例化原型原型(Prototype)(Prototype)用原形实例指定创建对象的种类,并通过拷贝原形来创用原形实例指定创建对象的种类,并通过拷贝原形来创建新的对象建新的对象单例单例(Singleton)(Singleton)保证一个类仅有一个实例,提供访问它的全局访问点保

5、证一个类仅有一个实例,提供访问它的全局访问点1. 构造式:对象创建的过程处理构造式:对象创建的过程处理6 设计模式设计模式 简要说明简要说明适配器适配器(Adapter)(Adapter)把类的接口转换成另外一个接口,解决接口不兼容问题。把类的接口转换成另外一个接口,解决接口不兼容问题。桥接桥接(Bridge)(Bridge)将对象的抽象和实现部分进行分离,使它们可以独立变化。将对象的抽象和实现部分进行分离,使它们可以独立变化。合成合成(Composite)(Composite)把对象组织成树形结构来表示层次关系,使对单个和复合对象把对象组织成树形结构来表示层次关系,使对单个和复合对象的使用具

6、有一致性。的使用具有一致性。装饰器装饰器(Decorator)(Decorator)动态地为对象添加新的操作功能。动态地为对象添加新的操作功能。外观外观(Facade)(Facade)把子系统中的各个接口统一为一致的接口。把子系统中的各个接口统一为一致的接口。享元享元(Flyweight)(Flyweight)运用共享技术支持细粒度的对象集合。运用共享技术支持细粒度的对象集合。代理代理(Proxy)(Proxy)以对象的名义对另一个对象进行访问。以对象的名义对另一个对象进行访问。2. 结构式:处理对象结构式:处理对象/类的组合类的组合7 设计模式设计模式 简要说明简要说明责任链责任链(Chai

7、n of (Chain of Responsibility)Responsibility)将不同对象对请求的处理形成一个链,使它们都有机会检查请求,将不同对象对请求的处理形成一个链,使它们都有机会检查请求,从而解除请求和处理者之间的耦合从而解除请求和处理者之间的耦合命令命令(Command Processor)(Command Processor)把请求封装为一个对象,可用不同的请求对客户进行参数化控制。把请求封装为一个对象,可用不同的请求对客户进行参数化控制。解释器解释器(Interpreter)(Interpreter)在给定语言和文法的情况下,建立一个该语言的解释器。在给定语言和文法的情

8、况下,建立一个该语言的解释器。迭代器迭代器(Iterator)(Iterator)在不暴露对象内部结构的情况下,循环访问一个对象的集合。在不暴露对象内部结构的情况下,循环访问一个对象的集合。协调器协调器(Mediator)(Mediator)使用一个中介,在对象不需要显式引用的情况下维持交互关系,使用一个中介,在对象不需要显式引用的情况下维持交互关系,从而达到维持对象松散耦合的作用。从而达到维持对象松散耦合的作用。备忘录备忘录(Memento)(Memento)在不破坏封装的前提下,获得对象内部状态的访问和控制权。在不破坏封装的前提下,获得对象内部状态的访问和控制权。观察者观察者(Observ

9、er)(Observer)建立对象与依赖它的对象之间的变化建立对象与依赖它的对象之间的变化-通知机制。通知机制。状态状态(state)(state)使对象在其内部状态发生变化时发生类似类行为的改变。使对象在其内部状态发生变化时发生类似类行为的改变。策略策略(Strategy/Policy)(Strategy/Policy)定义可以替换的算法,使得算法的变化可以独立于用户。定义可以替换的算法,使得算法的变化可以独立于用户。模板方式模板方式(Template (Template Method)Method)定义某个算法的计算过程框架,具体计算步骤到子类中加以实现,定义某个算法的计算过程框架,具体计

10、算步骤到子类中加以实现,在不改变算法构架的同时改变某些计算步骤的实现。在不改变算法构架的同时改变某些计算步骤的实现。访问者访问者(Visitor)(Visitor)表示作用于对象结构中各元素的操作,从而在不改变元素类的情表示作用于对象结构中各元素的操作,从而在不改变元素类的情况下定义对它们的新的操作。况下定义对它们的新的操作。. 行为式:处理对象间的交互方式和任务分布行为式:处理对象间的交互方式和任务分布设计模式的问题和解决方案问题:模式过多!Pattern Almanac 2000列出了大约500种设计模式,并且又发布了数百种模式。解决方案:找到根本原则大多数设计模式可以被视为少数几个GRA

11、SP基本原则的特化。这样除了能够有助于加速对详细设计模式的学习之外,而且对发现其根本的基本主题(防止变异、多态、间接性等)更为有效,它能够帮助我们透过大量细节发现应用设计技术的本质。适配器(Adapter)GoF名称:适配器(Adapter)问题:如何解决不相容的接口问题,或者如何为具有不同接口的类似构件提供稳定的接口?解决方案(建议):通过中介适配器对象,将构件的原有接口转换为其他接口适配器-示例例如,POS系统需要支持第三方外部服务,其中包括税金计算器、信用卡授权服务、库存系统和账务系统。它们都具有不同的API,而且无法改变。解决方案之一:增加一层间接性对象,通过这些对象将不同的外部接口调

12、整为在应用程序内使用的一致接口。适配器-示例适配器模式适配器-示例使用适配器适配器、外观的区别外观(Faade)是资源适配器使用单一对象封装了对子系统或系统的访问(外观的本质)。而当包装对象是为不同外部接口提供适配时,该对象才被特称为资源适配器适配器与某些GRASP核心原则的关系防止变异低耦合机制高内聚机制多态示例间接性机制纯虚构适配器工厂(Factory)该模式也称为简单工厂(Simple Factory)或具体工厂(Concrete Factory)。该模式不是GoF设计模式,它是GoF抽象工厂(Abstract Factory)模式的简化,应用极为广泛。适配器在设计中会引发一个新问题:在

13、前述适配器模式的解决方案中,对外部服务有不同的接口,那么是谁创建了这些适配器?并且如何决定创建哪种类的适配器,例如是创建TaxMasterAdapter还是GoodAsGoldTaxProAdapter?工厂(Factory)如果是某个领域对象来创建这些适配器,那么领域对象的职责会超出了单纯的应用逻辑(例如销售总额的计算),并且会涉及到与外部软件构件连接相关的其他内容。基本设计原则之一(通常被视为构架设计原则):设计要保持关注分离(separation of concern),将不同关注分离或模块化为不同领域,以确保内聚。工厂(Factory)常用的替代方案是使用工厂模式,其中定义纯虚构的“工

14、厂”对象来创建对象。工厂对象有如下一些优势:分离复杂创建的职责,并将其分配给内聚的帮助者对象隐藏潜在的复杂创建逻辑允许引入提高性能的内存管理策略,例如对象缓存或再生工厂(Factory)名称:工厂(Factory)问题:当有特殊考虑(例如存在复杂创建逻辑、为了改良内聚而分离创建职责等)时,应该由谁来负责创建对象?解决方案(建议):创建称为工厂的纯虚构对象来处理这些创建职责工厂(Factory)-示例工厂模式单例(Singleton)GoF工厂对象的设计引发了另一个新问题:由谁来创建工厂自身,如何访问工厂?首先,注意在该过程中只需要一个工厂实例。其次,因为在代码的不同位置都需要访问适配器以调用外

15、部服务,所以我们很快就会提出要在代码的不同位置调用工厂中的方法。因此,这里也存在可见性问题:如何获得单个ServicesFactory实例的可见性?单例(GoF)名称:单例(Singleton)问题:只有唯一实例的类即为“单例类”。对象需要全局可见性和单点访问。解决方案(建议):对类定义静态方法用以返回单例单例(GoF)-示例在ServiceFactory类中的单例模式策略(Strategy)GoF问题:如何提供较为复杂的定价逻辑,例如商店在某天的折扣、老年人折扣等等。销售的定价策略(也可以称为规则、政策或算法)具有多样性。在一段时期内,对于所有的销售可能会有10%的折扣,后期可能会对超出20

16、0元的销售给予10%的折扣,并且还会存在其他大量变化。我们如何对这些各种各样的定价算法进行设计?策略(GoF)名称:策略(Strategy)问题:如何设计变化但相关的算法或政策?如何设计才能是这些算法或政策具有可变更的能力?解决方案(建议):在单独的类中分别定义每种算法/政策/策略,并且使其具有共同接口。策略(GoF)定价策略类策略(GoF)协作中的策略策略(GoF)语境对象需要其策略的属性可视性使用工厂创建策略创建策略工厂-总结对于动态变化的定价策略的防止变异可以通过策略和工厂模式实现。建立在多态和接口基础上的策略可以实现具有可插拔的对象设计组合(Composite)GoF问题:我们如何来处

17、理多个互相冲突的定价策略?例如商店在今天(星期一)有效的政策有:对老年人有20%的折扣政策对于购物金额满400元的优先客户给予折15%的折扣在星期一,购物金额满500美元享受50元的折扣买一罐咖啡,则所有购物物品都享受15%的折扣假设一个老年人同时也是优先客户,他买了一罐咖啡和600元的物品。此时应该适用哪个定价政策?组合(GoF)名称:组合(Composite)问题:如何能够像处理非组合(原子)对象一样,(多态地)处理一组对象或具有组合结构的对象呢?解决方案(建议):定义组合和原子对象的类,使它们实现相同的接口组合(GoF)-示例组合模式组合(GoF)-示例与组合的协作创建多个SalePri

18、cingStrategies使用组合模式,我们使一组多个(有冲突)的定价策略对于Sale对象来说与单个定价策略一样。包含该组的组合对象也实现了ISalePricingStrategy接口。对于该设计问题更具有挑战性(并且更有趣)的部分是:我们什么时候创建这些策略?创建多个SalePricingStrategies良好的设计应该在开始时为商店创建一个包含当前所有折扣政策(如果没有有效折扣,可以设为0%)的组合,例如某个PercentageDiscountPricingStrategy。然后,如果在该场景的下一步中,发现还需要应用另一个定价策略(例如老年人折扣),此时通过使用继承来的Composi

19、tePricingStrategy.add方法,能够轻松地在组合中增加这一策略。在该场景中,可能有三个地方需要在组合中增加策略:商店当前定义的折扣,在创建销售时增加顾客类型折扣,在POS获知顾客类型时增加产品类型折扣(如果购买一罐咖啡,则所有购物物品都享受15%的折扣),在向销售输入该产品条目时增加创建多个SalePricingStrategies创建组合策略第二种顾客类型折扣为客户折扣创建定价策略(第一部分)为客户折扣创建定价策略(第二部分)外观(Faade)GoF问题:假设创建新销售时,可能要识别该销售是否以礼券方式进行支付(这是可能并且普遍的做法)。然后,商店可能会规定如果使用礼券只可以

20、购买一件商品。此时,enterItem在完成第一次操作后应该变为无效。如果销售使用礼券支付,在对该顾客找零时,除了礼券之外所有其他支付类型的找零都应该置为无效。例如,如果收银员请求现金找零或更新顾客在其商店帐户上的积分时,这些请求都应该被判断为无效。假设创建新销售时,可以识别其为慈善捐助(从商店到慈善机构)。商店可能会规定每次输入的条目价值只能低于250元,并且只有当前登录者为经理时才允许对该销售添加条目。外观(GoF)名称:外观(Faade)问题:对一组完全不同的实现或接口(例如子系统中的实现和接口)需要公共统一的接口。可能会与子系统内部的大量事物产生耦合,或者子系统的实现可能会改变。怎么办

21、?解决方案(建议):对子系统定义唯一的接触点使用外观对象封装子系统。该外观对象提供了唯一和统一的接口,并负责与子系统构件进行协作外观(GoF)具有外观的UML包图外观-总结外观模式很简单并且应用广泛。它将子系统隐藏在一个对象之后。外观通常通过单例模式进行访问。它们对子系统的实现提供了防止变异,并且通过增加间接性对象有助于低耦合的支持。外部对象只被耦合到子系统中的一个点:即外观对象适配器对象可能用来封装对具有不同接口的外部系统的访问。这就是一种外观,但是其强调的是对不同接口的适配,因此被更具体地称为适配器。观察者/发布-订阅/委派事件模型(GoF)问题:当总额变化后,GUI窗口要能刷新销售总额的

22、显示观察者(GoF)解决方案一:当Sale更新了总额后,Sale对象向窗口发生消息,使其刷新显示。模型-视图分离原则不提倡此类解决方案。它认为”模型“对象(诸如Sale这样的非UI对象)不应该知道像窗口这样的视图或表示对象。它改进了其他层与表示(UI)层对象的低耦合。支持这种低耦合的结果是,它允许替换现有视图或表示层,或者可以使用新的窗口来代替特定窗口,同时不会对非UI对象产生影响。例如,如果模型对象不知道Java Swing对象,那么就可能拔掉Swing接口,或者拔掉特定窗口,然后插入其他什么。因此,模型-视图分离对变化的用户界面提供了防止变异。观察者(GoF)名称:观察者(Observer

23、)(发布-订阅(Publish-Subscribe)问题:不同类型的订阅者对象关注与发布者对象的状态变化或事件,并且想要在发布者产生事件时以自己独特的方式作出反应。此外,发布者想要保持与订阅者的低耦合。如何对此进行设计呢?解决方案(建议):定义”订阅者“或”监视器“接口。订阅者实现此接口。发布者可以动态注册关注某事件的订阅者,并在事件发生时通知它们观察者(GoF)-示例观察者模式观察者(GoF)-示例观察者SaleFrame1向发布者Sale订阅观察者(GoF)-示例Sale向其所有订阅者发布特性事件观察者(GoF)-示例订阅者SaleFrame1接收已发布事件的通知观察者(GoF)-总结观察

24、者在对象通信方面提供了一种松耦合方式。发布者只通过接口获知订阅者,订阅者可以动态地向发布者注册(或取消注册)从前面的例子我们可以得出结论:基于模式的支持能够进行对象设计和职责分配。这些模式提供了一套可解释的惯用做法,设计良好的面向对象系统可以建立于该基础之上。抽象工厂(Abstract Factory)图中一共有四个产品族,分布于三个不同的产品等级结构中。只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一的确定这个产品。所谓的抽象工厂是指一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。如果用图来描述的话,如下图:53抽象工厂(Abstract Factory

25、)抽象工厂的起源据说最早的应用是用来创建在不同操作系统的视窗环境下都能够运行的系统 54可以发现上面产品类图有两个产品等级结构,分别是Button与Text;同时有两个产品族: Unix产品族与Windows产品族。55抽象工厂的起源系统对产品对象的创建要求由一个工厂的等级结构满足。其中有两个具体工厂角色,即UnixFactory和WinFactory。UnixFactory对象负责创建Unix产品族中的产品,而WinFactory负责创建Windows产品族中的产品。56抽象工厂的起源抽象工厂模式的结构57上图中的结构用产品族描述如下: 58抽象工厂模式中的四个角色抽象工厂抽象工厂(Abst

26、ract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。具体工厂具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。抽象抽象产品品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。具体具体产品品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。59在什么情

27、形下使用抽象工厂一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。 这个系统有多于一个的产品族,而系统只消费其中某一产品族。 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。60开放封闭原则开放封闭原则要求系统对扩展开放,展开放,对修改封修改封闭。通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:增加产品族:Abstract Factory很好的支持了开放封闭原则。增加新产品的等级结构:需要修改

28、所有的工厂角色,没有很好支持开放封闭原则。综合起来,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,而不能为新的产品等级结构的增加提供这样的方便。61桥接(Bridge)从蜡笔与毛笔说起 设想要绘制一幅图画,蓝天、白云、绿树、小鸟,如果画面尺寸很大 ,总共3种大写12种颜色,是用毛笔还是用蜡笔更方便呢? 62显而易见用蜡笔需要3*12=36只,而毛笔是3+12=15,而且颜色越多用毛笔的优势越明显这就是Bridge模式 :将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化 63桥接(Bridge)桥接模式三个关键词抽

29、象化:抽象化: 存在于多个实体中的共同的概念性联系,就是抽象化。作为一个过程,抽象化就是忽略一些信息,从而把不同的实体当做同样的实体对待。实现化:化: 抽象化给出的具体实现,就是实现化。脱耦:脱耦:所谓耦合,就是两个实体的行为的某种强关联。而将它们的强关联去掉,就是耦合的解脱,或称脱耦。在这里,脱耦是指将抽象化和实现化之间的耦合解脱开,或者说是将它们之间的强关联改换成弱关联。将两个角色之间的继承关系改为聚合关系,就是将它们之间的强关联改换成为弱关联。64桥接模式的结构65桥接模式所涉及的角色抽象化抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。修正抽象化修

30、正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。实现化化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。 具体具体实现化化(Concrete Implementor)角色:这个角色给出实现化角色接口的具体实现。 66在什么情况下使用桥接模式如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系

31、。 设计要求实现化角色的任何改变不应当影响客户端,或者说实现化角色的改变对客户端是完全透明的。 一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态耦合。 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。 实例(Brush.cs)67总结 设计模式建立在对系统变化点的基础上进行,哪里有变化点,哪里应用设计模式。 设计模式应该以演化的方式来获得,系统的变化点往往是经过不断演化才能准确定位。 不能为了模式而模式,设计模式是一种软件设计的软力量,而非规范标准。不应夸大设计模式的作用。68推荐书籍设计模式Gamma、Helm、Johnson和VlissidesHead First 设计模式面向模式的软件体系结构69谢谢大家!70

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 医学/心理学 > 基础医学

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号