版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、哈尔滨工业大学计算机学院唐好选Email:主要内容主要内容p软件设计模式基础p创建型模式p结构型模式p行为型模式软件设计模式基础p 广义讲,软件设计模式是可解决某类软件问题并能重复使用的软件设计方案p 狭义讲,软件设计模式是“对特定场景下解决一般设计问题的类和相互通信对象的描述”。是在类和对象的层次描述的可重复使用的软件设计问题的解决方案p 模式体现程序整体构思,也会出现在分析或概要设计阶段 p 模式的核心思想:通过增加抽象层,把变化部分从那些不变部分里分离出来设计模式的概念设计模式的概念(1)模式名称(Pattern Name)(2)问题(Problem):描述应在何时使用模式。解释了设计问
2、题和问题存在的前因后果,可能还描述模式必须满足的先决条件(3)解决方案(Solution):描述设计的组成成分、相互关系及各自的职责和协作方式。模式就像一个模板,可用于多种场合,所以解决方案并不描述一个具体的设计或实现,而是提供设计问题的抽象描述和解决问题所采用的元素组合(类和对象)(4)效果(consequences ):描述模式的应用效果及使用模式应权衡的问题模式的基本要素模式的基本要素p模式名和分类p意图:设计模式是做什么的?它的基本原理和意图是什么?它解决的是什么样的特定设计问题?p动机:说明一个设计问题以及如何用模式中的类、对象来解决该问题的特定情景p适用性:什么情况下可以使用该设计
3、模式?该模式可用来改进哪些不良设计?如何识别这些情况?p结构:采用对象建模技术对模式中的类进行描述如何描述设计模式如何描述设计模式p参与者:指设计模式中的类 和/或 对象以及它们各自的职责p协作:模式的参与者如何协作并实现其职责p效果:模式如何支持其目标?使用模式的效果和所需做的权衡取舍?系统结构的哪些方面可以独立改变?p实现:实现模式时需了解的一些技术要点及应避免的缺陷,以及是否存在某些特定于实现语言的问题p代码示例:说明怎样实现该模式的代码片段p相关模式:与这个模式紧密相关的模式有哪些?其不同之处是什么?这个模式应与哪些其他模式一起使用?描述设计模式(续)描述设计模式(续)设计模式的原则设
4、计模式的原则p 开-闭原则(Open Closed Principal)p 单一职责原则(Single Responsibility Principle )p 里氏替换原则(Liskov Substitution Principle )p 依赖倒置原则(Dependence Inversion Principle )p 接口隔离原则(Interface Segregation Principle )p 迪米特法则(最少知道原则)(Least Knowledge Principle)p 设计模式就是实现了上述原则,从而达到代码复用、增加可维护性的目的p 定义:对扩展是开放的,对修改是关闭的。开发
5、软件时,可对其功能进行扩展(开放),进行扩展时,不需要对原程序进行修改(关闭)p 优点p 软件可用性较灵活,可对完成后的软件进行扩展,加入新功能,可通过不断增加新模块满足不断变化的新需求p 由于不修改软件原有的模块,不用担心软件的稳定性开闭原则(开闭原则(OCP)u就一个类而言,应该仅有一个引起它变化的原因。每一个引起类变化的原因就是一个职责,当类具有多职责时,应把多余职责分离出去,分别创建一些类来完成每一个职责u每一个职责都是一个变化的轴线,当需求变化时会反映为类的职责的变化举例: interface Modem public void dial(String pno); public vo
6、id hangup(); public send(char c); public char recv(); Modem类有两个职责:连接管理和数据通信,应将它们分离单一职责原则(单一职责原则(SRP)interface ModemCon public void dial(String pno); public void hangup(); interface ModemCom public send(char c); public char recv(); 里氏替换原则(里氏替换原则(LSP)p 里氏替换原则是继承复用的基石,只有当派生类可以替换掉其基类,而软件功能不受影响时,基类才能真正被复
7、用,派生类也才能够在基类的基础上增加新的行为p LSP本质:在同一个继承体系中的对象应该有共同的行为特征p 例子:企鹅是鸟吗? 生物学:企鹅属于鸟类 LSP原则:企鹅不属于鸟类,因为企鹅不会“飞”p 违反LSP的后果:有可能需要修改客户代码依赖倒置原则(依赖倒置原则(DIP)p 高层模块不应依赖于低层模块,二者都依赖于抽象;抽象不应该依赖细节;细节应该依赖抽象p 高层模块只应该包含重要的业务模型和策略选择,低层模块则是不同业务和策略的实现p 高层抽象不依赖高层和低层模块的具体实现,最多只依赖于低层的抽象p 低层抽象和实现也只依赖于高层抽象 p 辅助原则 p 任何变量都不应该持有一个指向具体类的
8、引用p 任何类都不应该从具体类派生p 任何方法都不应覆盖其任何基类中已经实现了的方法 接口隔离原则(接口隔离原则(ISP)p使用多个专门的接口比使用单一的总接口要好 p一个类对另一个类的依赖性应当建立在最小的接口上 p一个接口代表一个角色,不应当将不同的角色都交给一个接口,没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染p“不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。”换句话说,不要强迫客户使用它们不用的方法,如果强迫用户使用它们不用的方法,那么这些客户就会面临由于这些不使用方法的改变所带来的改变最少知道原则(最少知道原则(LKP)p 一个
9、软件实体应当尽可能少地与其他实体发生相互作用p 每一个软件单位对其他单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位p 迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系 p在设计模式经典著作GOF95中,设计模式从应用的角度被分为三大类型 p创建型模式/结构型模式/行为型模式p根据模式应用范围分,模式可应用于类,也可应用于对象p类模式:处理类和子类之间的关系,这些关系通过继承建立,是静态的,在编译时刻便确定下来了p对象模式:处理对象间的关系,这些关系在运行时刻是可以变化的,更具动态性
10、p从某种意义上来说,几乎所有模式都使用继承机制,所以“类模式”只指那些集中于处理类间关系的模式,而大部分模式都属于对象模式的范畴设计模式的类型设计模式的类型p 创建型设计模式是用来创建对象的模式,该类模式抽象了实例化过程 p 工厂模式:父类负责定义创建对象的公共接口,而子类则负责生成具体对象,将类的实例化操作延迟到子类中完成p 抽象工厂模式:为一个产品族提供统一的创建接口。当需要这个产品族的某一系列的时候,可以从抽象工厂中选出相应的系列创建一个具体的工厂类p 单件(Singleton)模式:保证一个类有且仅有一个实例,提供一个全局访问点创建型设计模式创建型设计模式创建型设计模式创建型设计模式p
11、 生成器(Builder)模式:将复杂对象创建与表示分离,同样的创建过程可创建不同的表示。允许用户通过指定复杂对象类型和内容来创建对象,用户不需要知道对象内部的具体构建细节p 原型(Prototype)模式:通过“复制”一个已经存在的实例来返回新的实例(不新建实例)。被复制的实例就是“原型”,这个原型是可定制的。原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效p 结构型模式讨论的是类和对象的结构,它采用继承机制来组合接口或实现(类结构型模式),或者通过组合一些对象来实现新的功能(对象结构型模式)p 组合(Composite)模式:定义一个接口,使之
12、用于单一对象,也可以应用于多个单一对象组成的对象组p 装饰(Decorator)模式:给对象动态添加额外的职责,就好像给一个物体加上装饰物,完善其功能p 代理(Proxy)模式:有些对象由于跨越网络或其他障碍,而不能或者不想直接访问另一个对象,直接访问会给系统带来不必要的复杂性,这时候可以在客户程序和目标对象之间增加一个中间代理对象,让代理对象来代替目标对象结构型设计模式结构型设计模式结构型设计模式结构型设计模式p 享元(Flyweight)模式:享元是一个共享对象,它可以同时在不同上下文(Context)使用p 外观(Facade)模式:外观模式为子系统提供了一个更高层次、更简单的接口,从而
13、降低了子系统的复杂度,使子系统更易于使用和管理。外观承担了子系统中类交互的责任p 桥梁(Bridge)模式:桥梁模式的用意是将问题的抽象和实现分离开来实现,通过用聚合代替继承来解决子类爆炸性增长的问题p 适配器(Adapter)模式:将一个类的接口适配成用户期待接口。一个适配器允许因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包装在一个已存在的类中 p 着力解决的是类实体之间的通讯关系,希望以面向对象的方式描述一个控制流程p 模版(Template ) 模式:定义了一个算法步骤,并允许子类为一个或多个步骤提供实现。子类在不改变算法架构的情况下,可重新定义算法中某些步骤p 观
14、察者(Observer)模式:定义了对象之间一对多的依赖,当这个对象的状态发生改变的时候,多个对象会接受到通知,有机会做出反馈p 迭代子(Iterator)模式:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示行为型设计模式行为型设计模式p 责任链(Chain of Responsibility)模式:多个对象由每一个对象对其下一个对象的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使系统可以在不影响客户端的情况下动态的重新组织链和分配责任p 备忘录(Memento)模
15、式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态p 命令(Command)模式:将请求及其参数封装成一个对象,作为命令发起者和接收者的中介,可以对这些请求排队或记录请求日志,以及支持可撤销操作行为型设计模式行为型设计模式p 状态(State)模式:允许一个“对象”在其内部状态改变的时候改变其行为,不同状态表现不同行为p 访问者(Visitor)模式:表示作用于某对象结构中的各元素的操作。可在不改变元素类的前提下定义作用于这些元素的新操作p 解释器(Interpreter) 模式:给定一个语言,定义其文法的表示,并定义一个解
16、释器,该解释器使用文法表示来解释语言中的句子p 中介者(Mediator)模式:用一个中介对象来封装一系列的对象交互p 策略(Strategy)模式:定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。策略模式使这些算法在客户端调用它们的时候能够互不影响地变化行为型设计模式行为型设计模式创建型设计模式p工厂模式p抽象工厂模式p建造者模式p单件模式p原型模式创建型设计模式创建型设计模式p 在面向对象编程中, 使用new操作符构造对象实例是一种常规方法,但该方法存在一些约束条件和缺陷:(1)创建对象前须明确对象的类信息,但某些情况可能无法达到此要求,譬如打开一个视频文件需要一个播放器对象,
17、但用户可能并不知道具体播放器,需要系统分派一个合适的播放器(2)复杂对象的创建需要多个步骤p 需计算或取得对象的初始设置p 需选择生成哪个子对象实例p 在生成所需对象之前必须先生成一些辅助对象p 新对象的创建是一个“过程”,而不是一个简单操作。为了能方便完成这些复杂对象的创建工作,可引入工厂模式 工厂模式的由来工厂模式的由来工厂模式的结构工厂模式的结构p Product:定义工厂方法所创建对象的接口p ConcreteProduct:实现Product接口p Factory:声明工厂方法,返回一个Product对象。Factory也可定义工厂方法的缺省实现,返回一个缺省ConcreteProd
18、uct对象p Concrete Factory:重定义工厂方法,返回一个ConcreteProduct对象工厂模式的参与者工厂模式的参与者p日志管理器,支持两种类型日志pFileLogpEventLog工厂模式实例工厂模式实例/ LogFactory类public abstract class LogFactory public abstract Log Create();工厂模式实例分析工厂模式实例分析/ FileFactory类 public class FileFactory:LogFactory public override FileLog Create() return new F
19、ileLog(); / EventFactory类 public class EventFactory:LogFactory public override EventLog Create() return new EventLog(); public class App public static void Main(string args) LogFactory factory1 = new EventFactory(); FileFactory factory2 = new FileFactory(); Log log1 = factory1.Create(); Log log2 = f
20、actory2.Create(); log1.Write(); log2.Write(); 工厂模式客户端程序工厂模式客户端程序p 有效避免了具体产品对象和应用程序之间的耦合,增加了具体工厂对象和应用程序之间的耦合p 在类内部创建对象通常比直接创建对象更灵活p 工厂模式通过面向对象的手法,将具体对象的创建工作延迟到子类,提供了一种扩展策略,较好的解决了紧耦合问题工厂模式实例分析工厂模式实例分析抽象工厂模式的由来抽象工厂模式的由来p 在软件系统中,经常面临“一系列相互依赖对象”的创建工作,由于需求变化,“一系列相互依赖的对象”也要改变,如何应对这种变化呢?如何像工厂模式一样绕过常规的”new”,
21、提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?p 一种说法:可以通过工厂模式创建每个对象,但无法保证“相互依赖对象”之间的联系 p 实例:Windows桌面主题,当更换一个桌面主题的时候,系统的开始按钮、任务栏、菜单栏、工具栏等都变了,而且是一起变的,色调都保持一致,类似这样的问题如何解决呢?p 应用抽象工厂模式,是一种有效的解决途径抽象工厂模式的意图抽象工厂模式的意图p意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类p适用场合p一个系统由多个产品系列中的一个来配置时p强调一系列相关产品对象的设计以便进行联合时p提供一个产品类库,只想显示其
22、接口而非实现时p需要创建的对象是一系列相互关联或相互依赖的产品族时抽象工厂模式的结构抽象工厂模式的结构p Abstract Factory:声明创建抽象产品对象的操作接口p ConcreteFactory:实现创建具体对象的操作p Abstract Product:为一类产品对象声明一个接口p ConcreteProduct:定义一个被具体工厂创建的产品对象抽象工厂模式的参与者抽象工厂模式的参与者实例:需要设计一个花园布局 花园有三种风格:典雅型、实用型和懒人型 花园中有3个位置需要种植植物:花台、墙角和花园中心抽象工厂模式的应用实例抽象工厂模式的应用实例风格/位置花台中心墙角典雅型郁金香榕树
23、兰草实用型葡萄石榴丝瓜懒人型月季茶花竹子建造者(建造者(Builder)模式的由来)模式的由来p 在软件系统中,有时面临“复杂对象”的创建工作,该复杂对象通常由各个部分的子对象用一定的算法构成p 这个复杂对象的各个部分经常面临剧烈变化,但是将它们组合在一起的算法却相对稳定p 如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?建造者模式的意图和适用性建造者模式的意图和适用性p 意图:将一个复杂的构建与表示相分离,使得同样的构建过程可以创建不同的表示p 适用性场合p 需要生成的产品对象有复杂的内部结构p 创建复杂对
24、象的算法稳定,或可强迫生成一定顺序p 当构造过程允许被构造的对象有不同的表示时建造者模式的结构建造者模式的结构建造者模式的参与者建造者模式的参与者p Builder:为创建一个Product对象的各个部件指定抽象接口p ConcreteBuilder:实现Builder接口来构造和装配产品各个部件,提供一个检索产品的接口p Director:构造一个使用Builder接口的对象p Product:表示被构造的复杂对象p 实例:设计游戏场景中的房屋p房屋由五个部分组成:地板、墙壁、窗户、门和天花板p构建房屋的步骤固定,而具体组件(门、窗等)易变p采用建造者模式分离易变组件和稳定的构建过程建造者模
25、式的应用示例建造者模式的应用示例public abstract class House /定义一个房屋抽象类 public abstract class Builder /这部分是易变的 public abstract void BuildFloor(); /地板 public abstract void BuildDoor(); /门 public abstract void BuildWindows(); /窗户 public abstract void BuildWall(); /墙壁 public abstract void BuildHouseCeiling() /天花板 publi
26、c abstract House GetHouse(); 建造者模式的应用示例建造者模式的应用示例建造者模式的应用示例建造者模式的应用示例public abstract class GameManager /规定构建次序 public static House CreateHouse(Builder builder) builder.BuildFloor(); builder.BuildDoor(); builder.Buildwall(); builder.BuildWindows(); builder.BuildHouseCeiling(); return builder.GetHouse
27、(); 建造者模式的应用示例建造者模式的应用示例public class RomanHouseBuilder : Builder public override void BuildDoor() public override void BuildFloor() public override void BuildWindows() public override void BuildWall() public override void BuildHouseCeiling() public override House GetHouse() 建造者模式的应用示例建造者模式的应用示例class
28、 App public static void main() House house = GameManager.CreateHouse(new RomanHouseBuilder(); 建造者模式分析建造者模式分析p 建造者模式的使用使产品内部表象可以独立变化;可以使客户端不必知道产品内部组成细节p 每一个Builder都相对独立,与其它Builder无关p 可对构造过程更加精细控制p 将构建代码和表示代码分开p 缺点:难于应付“分步骤构建算法”的需求变动单件(单件(SingletonSingleton)模式的由来)模式的由来p 单件模式的实例较为普遍:p 系统中只能有一个窗口管理器p 系统
29、中只能有一个文件系统p 一个数字滤波器只能有一个A/D转换器p 一个会计系统只能用于一个公司单件模式的由来单件模式的由来p 如何才能保证一个类只有一个实例并且这个实例易于被访问呢?全局变量使得一个对象可以被访问,但不能防止实例化多个对象p 更好的办法: 让类自身保存其唯一实例,可以保证该类没有其他实例可以被创建,并且它可以提供一个访问该实例的方法单件模式的意图和适用性单件模式的意图和适用性p 意图:保证一个类仅有一个实例,并提供一个全局访问点p 适用场合:p 当类只能有一个实例而且需要使用户可从一个统一访问点访问它时p 当这个唯一实例通过子类化可扩展,并且客户应该无需更改代码就能使用一个扩展实
30、例时单件模式的结构单件模式的结构p Singleton :被调用的单件对象p 定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作(静态成员函数) ,负责创建自己的唯一实例单件模式的应用示例单件模式的应用示例Class Singleton /单件模式的定义 public:static Singleton* Instance(); /通过该成员函数访问单件 protected:Singleton(); /构造函数为受保护型,直接实例化将出错 private:static Singleton* _instance; /指向本身唯一实例的指针;单件模式的应用示例单件模
31、式的应用示例Singleton * Singleton:_instance = 0; /初始化类成员Singleton* Singleton:Instance()If(_instance = 0) _instance =new Singleton; return _instance;单件模式的效果分析单件模式的效果分析p 可实现对唯一实例的受控访问:因为Singleton类封装唯一实例,所以它可以严格的控制客户怎样以及何时访问它p 缩小了名空间:Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染名空间原型(原型(Prototype)模式的由来)模式的由来p 在
32、软件系统中,客户希望创建一个产品时,可能有三种情况:p 知道产品具体型号:使用new运算符创建p 不知道产品型号,知道特定的需求:使用工厂模式p 不知道需求,但想要一个和已知对象相同的对象:使用原型模式原型(原型(Prototype)模式的意图和适用性)模式的意图和适用性p 意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象p 适用性:p 一个系统独立于其产品创建,构成和表示时p 要实例化的类在运行时刻指定时p 为避免创建一个与产品类层次平行的工厂类层次时原型模式的结构原型模式的结构p Client:客户端向原型管理器提出创建对象请求p Prototype:是对各种具体原型的
33、抽象,通常由一个接口或抽象类实现p ConcretePrototype:被复制的对象。此角色需要实现抽象的原型角色所要求的接口p PrototypeManager:创建具体原型类的对象,记录每一个被创建的对象原型模式的参与者原型模式的参与者p 开发一个调色板,用户单击调色板上任一个方块,返回一个对应颜色的实例p 把每种颜色作为一个对象,并为他们抽象出一个公共父类原型模式应用示例原型模式应用示例原型模式应用示例原型模式应用示例p 优点(1)对客户隐藏具体产品类,减少了客户知道的名字的数目(2)允许客户只通过注册原型实例就可以将一个具体产品类并入系统中,客户可以在运行时刻建立和删除原型(3)具有给
34、一个应用软件动态加载新功能的能力。由于其独立性较高,可以很容易动态加载新功能而不影响老系统(4)产品类不需要非得有任何事先确定的等级结构,适用于任何的等级结构p 缺点 Prototype模式的最主要缺点就是每个类必须配备一个克隆方法原型模式的应用效果分析原型模式的应用效果分析p 工厂模式是一种极端情况下的抽象工厂模式,而抽象工厂模式可以看成是工厂模式的一种推广p 工厂模式的特点p一个抽象产品类,可以派生出多个具体产品类p一个抽象工厂类,可以派生出多个具体工厂类p每个具体工厂类只能创建一个具体的产品类实例p 抽象工厂模式的特点p多个抽象产品类,每个抽象产品类可以派生出多个具体产品类p一个抽象工厂
35、类,可以派生出多个具体工厂类p每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式与工厂模式的区别抽象工厂模式与工厂模式的区别p抽象工厂允许客户使用抽象接口来创建一组相关产品,而不需要关心具体产出产品是什么p总结p 所有工厂都是用来封装对象的创建p 简单工厂,可以把客户程序从具体类解耦p 工厂方法使用继承,把对象创建委托给子类,子类实现工厂方法来创建对象p 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中p 所有工厂模式都通过减少应用程序与具体类之间的依赖关系促进松耦合p 工厂方法允许类将实例化延迟到子类进行p 抽象工厂创建相关的家族,而不需要依赖他们的具体类p 工厂帮助我
36、们针对抽象编程,而不是针对具体类编程抽象工厂模式与工厂模式的区别抽象工厂模式与工厂模式的区别p 工厂模式:定义一个创建对象的接口,由子类决定要实例化的具体类,工厂方法让类把实例化推迟到子类p 抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类p 建造者模式:封装一个产品(复杂对象)的构造过程,并允许按照步骤构造,向客户隐藏了产品的内部表现p 单件模式:确保一个类只有一个实例,并提供全局访问点p 原型模式:当创建给定类实例的过程很昂贵或很复杂时,使用原型模式,向客户隐藏制造新实例的复杂性创建型设计模式总结创建型设计模式总结结构型设计模式p 适配器模式p 外观模式p
37、装饰模式p 桥接模式p 享元模式p 代理模式p 组合模式结构型模式的主要内容结构型模式的主要内容软件开发过程中常见的问题软件开发过程中常见的问题p 系统组件更新问题:软件系统的某组件过时了,要从厂商那里引进一个新的组件,但原系统的组件接口和新组件的接口不一致,同时又不想改变现有的代码,如何实现从旧组件更新到新组件现有现有系统系统接口接口厂厂商商类类两个接口两个接口无法匹配,无法匹配,所以无法所以无法工作工作软件开发过程中常见的问题软件开发过程中常见的问题p 生活中相似问题的解决方案不合适的插座问题p 电脑的插头是三相的p 墙上的插座只有两相的p 插头和插座的“接口”不匹配,怎么办?组件更新问题
38、的可行解决方案组件更新问题的可行解决方案现有现有系统系统接口接口厂厂商商类类两个接口两个接口无法匹配,无法匹配,所以无法所以无法工作工作现有现有系统系统接口接口厂厂商商类类适适配配器器适配器模式的动机适配器模式的动机p 一个team要为外界提供S类服务,但team里面没有能够完成此项任务的member,只有team外的A可以完成这项服务。为保证对外服务类别的一致性(能提供S服务)p 将A招安到team内,负责提供S类服务p A不准备接受招安,可安排B去完成这项任务,并让B做好A的工作,让B工作的时候向A请教,此时,B是一个复合体(提供S服务,是A的继承弟子)p 动机:将一个类的接口,转换成客户
39、期望的另一个接口,适配器让原本接口不兼容的类可以一起工作适配器模式使用过程适配器模式使用过程p 客户(Client)通过目标接口调用适配器(Adapter)的方法对适配器发出请求p 适配器(Adapter)使用被适配者(Adaptee)接口把请求转换成被适配者的一个或者多个调用接口p 客户接收到调用的结果,但并未察觉这一切是适配器在起转换作用适配器模式的适用性适配器模式的适用性p 适用场合:p 使用一个已经存在的类,而它的接口不符合要求p 创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作p 使用一些已经存在的子类,但不可能通过子类化以匹配各自
40、接口。对象适配器可以适配它的父类接口p 分类:p 类适配器:通过多重继承匹配一个接口和另一个接口p 对象适配器:在一个类中定义另一个类的实例对象,实现类和对象的组合类适配器类适配器p 用一个具体的Adapter类对Adaptee和Target进行匹配,Adapter类多重继承Adaptee和Target类p Adapter可重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类类适配器模式示例类适配器模式示例/Target:定义Client使用的与特定领域相关的接口 public interface Target void request(); /Adaptee:需要适配
41、的已经存在的接口 public class Adaptee public void specificRequest() /Adapter:对对Adaptee 的接口与的接口与Target接口进行适配接口进行适配 public class Adapter extends Adaptee implements Target public void request() super. specificRequest(); 对象适配器对象适配器p 允许一个Adapter与多个Adaptee同时工作,即Adaptee本身以及它的所有子类(如果有子类的话)同时工作。Adapter可以一次给所有的Adapte
42、e添加功能p 使用组合,不仅可以适配某个类,也可以适配该类的任何子类对象适配器模式示例对象适配器模式示例/Target:定义Client使用的与特定领域相关的接口 public interface Target void request(); /Adaptee:现在需要适配的已经存在的接口 public class Adaptee public void specificRequest() /Adapter:对对Adaptee 的接口与的接口与Target接口进行适配接口进行适配 public class Adapter implements Target private Adaptee ad
43、aptee; public Adapter(Adaptee adaptee) super(); this.adaptee = adaptee; public void request() adaptee.specificRequest(); 适配器模式效果分析适配器模式效果分析p 优点p 方便设计者自由定义接口,不用担心匹配问题p 缺点p 属于静态结构 ,由于只能单继承,所以不适用于多种不同的源适配到同一个目标两种适配器模式的比较两种适配器模式的比较外观(外观(Facade)模式的由来)模式的由来毕业生教务处公安处后勤处图书馆饭卡饭卡余额借书证借书证押金身份证、学生证派遣证学生证毕业证、学位证
44、外观(外观(Facade)模式的由来)模式的由来毕业生毕业手续代办处教务处后勤处图书馆公安处学生证 身份证 借书证 饭卡毕业证 学位证 派遣证 饭卡余额 借书证押金外观(外观(Facade)模式的由来)模式的由来外观外观(Faade)模式的由来模式的由来外观(外观(Facade)模式的意图和适用性)模式的意图和适用性p 提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用p 解除客户程序对抽象类具体实现部分的依赖,有利于移植和更改p 当需要构建层次结构的子系统时,使用Faade模式定义每层入口点。如果子系统间相互依赖,只需通过Faade进行通讯p 外观模
45、式的本质是让接口变得更简单外观(外观(Facade)模式的结构)模式的结构外观(外观(Facade)模式的参与者)模式的参与者p Faadep 知道哪些子系统类负责处理请求p 将客户的请求代理给适当的子系统对象p Subsystem Classesp 实现子系统的功能p 处理由Faade 对象指派的任务p 没有Faade的任何相关信息外观(外观(Facade)模式的效果分析)模式的效果分析p 根据“单一职责原则”,在软件中将一个子系统划分为若干个子系统有利于降低整个系统的复杂性,一个常见的设计目标是使子系统之间的通信和相互依赖关系达到最小,而达到该目标的途径之一就是引入一个外观对象,它为子系统
46、的访问提供了一个简单而单一的入口p 外观模式也是“迪米特法则”的体现,通过引入一个新的外观类可以降低原有系统的复杂度,同时降低客户类与子系统类的耦合度外观(外观(Facade)模式的效果分析)模式的效果分析p 外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交道p 外观模式的目的在于降低系统的复杂程度p 外观模式从很大程度上提高了客户端使用的便捷性,使得客户端无须关心子系统的工作细节,通过外观角色即可调用相关功能p 如何增加新的子系统?是否可能违背“开闭原则”外观(
47、外观(Facade)模式的缺点)模式的缺点p 不能很好的限制客户使用子系统类,如果对客户访问子系统类做太多的限制,则减少了可变形和灵活性p 增加一个新的子系统,可能需要修改外观类或客户端的源代码,违背了“开闭原则”,怎么办?p 引入抽象外观类,客户端针对抽象外观类编程装饰(装饰(Decorator)解决的问题)解决的问题p 新买一辆车,但外表不够美观p 对车的外表进行必要的装饰装饰(装饰(Decorator)模式的由来)模式的由来p 动态给对象添加额外职责。比如:一幅画有没有画框都可以挂在墙上,画是被装饰者。在挂在墙上之前,画可以被蒙上玻璃,装到框子里,玻璃画框就是装饰p 不改变接口,但加入了
48、责任。Decorator提供了一种给类增加职责的方法,不是通过继承,而是通过组合实现的装饰(装饰(Decorator)模式的意图和适用性)模式的意图和适用性p 意图p 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式比生成子类更为灵活p 适用场合p 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责p 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立扩展,每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况是因为类定义被隐藏,或类定义不能用于生成子类装饰(装饰(Decorator)模式的结构)模式的结构p Component:定
49、义对象的接口,可以给对象动态添加职责p ConcreteComponent:定义具体对象,装饰抽象类可以给它添加额外的职责p Decorator:维持一个指向Component对象的指针,并定义一个与Component接口一致的接口p ConcreteDecorator:具体装饰对象,向具体对象添加职责p Decorator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加的动作装饰(装饰(Decorator)模式的结构)模式的结构装饰(装饰(Decorator)模式的应用)模式的应用ComponentConcreteComponent装饰(装饰(Decorator)模
50、式的应用)模式的应用Decorator装饰(装饰(Decorator)模式的应用)模式的应用ConcreteDecorator装饰(装饰(Decorator)模式的应用)模式的应用装饰(装饰(Decorator)模式的评价)模式的评价p 使用Decorator模式可以很容易地向对象添加职责。可以用添加和分离的方法,在运行时添加和删除职责p 使用Decorator模式可以很容易地重复添加一个特性,而两次继承则极容易出错p 避免在层次结构高层的类有太多的特征:可以从简单的部件组合出复杂的功能。具有低依赖性和低复杂性桥接(桥接(Bridge)模式的由来)模式的由来p 例子:设想如果要绘制矩形、圆形、
51、椭圆、正方形,至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案p 为每一种形状都提供一套各种颜色的版本p 根据实际需要对形状和颜色进行组合桥接(桥接(Bridge)模式的由来)模式的由来12方案表示桥接模式,将继承关系转换为关联关系,降低了类与类之间的耦合,减少了代码量桥接(桥接(Bridge)模式的由来)模式的由来p 例子:相同模块的跨平台使用p 设计模块A和Bp 希望模块A和B能应用在X操作系统上,让A和B继承X操作系统的接口p 希望模块A和B能应用在Y操作系统上,让A和B继承Y操作系统的接口,以此类推p 问题:模块A和B缺乏复用性
52、p 解决:抽象出统一的操作系统类的接口连接模块A和B的平台无关接口,通过桥接两个抽象模块来消除模块间的继承耦合,提高复用性扩展Window抽象使之用于不同种类的窗口或新的平台很不方便继承机制使得客户代码与平台相关桥接(桥接(Bridge)模式的由来)模式的由来1将Window抽象和它的实现部分分别放在独立的类层次结构中针对窗口接口针对平台的窗口实现桥接(桥接(Bridge)模式的由来)模式的由来2u对于有两个变化维度(即两个变化的原因)的系统,采用方案二进行设计,系统中类的个数更少,且系统扩展更为方便u设计方案二即是桥接模式的应用。桥接模式将继承关系转换为关联关系,从而降低了类与类之间的耦合,
53、减少了代码量桥接(桥接(Bridge)模式的动机)模式的动机桥接(桥接(Bridge)模式的意图和适用性)模式的意图和适用性p 意图:桥接模式的作用就是将抽象部分与实现部分分离,使它可以独立的变化p 适用的情况p 不希望在抽象和它的实现部分之间有一个固定的绑定关系p 想对客户完全隐藏抽象的实现部分桥接(桥接(Bridge)模式的结构)模式的结构桥接(桥接(Bridge)模式的参与者)模式的参与者p Abstractionp 定义抽象类的接口p 维护一个指向Implementor类型对象的指针p RefinedAbstractionp 扩充由Abstraction定义的接口p Implement
54、orp 定义实现类的接口,不一定要与Abstraction的接口完全一致,甚至可以完全不同p ConcreteImplementorp 实现Implementor接口并定义它的具体实现p Abstraction将Client的请求转发给它的Implementor对象桥接(桥接(Bridge)模式的意义)模式的意义p 脱耦是指将抽象和实现之间的耦合解脱开,或者说将他们之间的强关联改成若弱关联p 强关联是指在编译时期已经确定的,无法在运行时期动态改变的关联p 弱关联是可以动态确定并可在运行时刻动态改变的关联p 继承关系是强关联,聚合关系是弱关联,将两个角色之间的继承关系修改为聚合关系,就是将他们之
55、间的强关联变换成弱关联。桥模式中的所谓脱耦就是指在一个软件系统的抽象和实现之间使用组合/聚合关系而不是继承关系,从而可以使两者可以相对独立的变化桥接(桥接(Bridge)模式的优点)模式的优点p分离抽象接口及其实现部分 p桥接模式有时类似于多继承方案,但是多继承方案违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差,而且多继承结构中类的个数非常庞大,桥接模式是比多继承方案更好的解决方法p桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统p实现细节对客户透明,可以对用户隐藏实现细节桥接(桥接(Bridge)模式的缺点)模式的缺点p桥接模式的引入会
56、增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程p桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性桥接(桥接(Bridge)模式的应用案例)模式的应用案例桥接(桥接(Bridge)模式的应用案例)模式的应用案例享元(享元(Flyweght)模式的由来)模式的由来享元(享元(Flyweght)模式的由来)模式的由来p 当大量使用同一种类型的实例(每个实例中包含部分相同的数据),可能极大的耗费资源,使用Flyweight模式可以提高内存效率p 以CD唱片为例,每个CD有三个属性:出片日期、歌唱者姓名、唱片曲目p 姓名可能重复,可
57、能有同一个演唱者的多个不同时期不同曲目的CD。歌唱者姓名可共享,其他字段均不可共享p 当你有几千张甚至更多CD时,Flyweight模式将节省更多空间,共享的flyweight越多,空间节省也就越大享元(享元(Flyweght)模式的意图和适用性)模式的意图和适用性p 意图:避免大量拥有相同内容的小类的开销,共享一元类p 动机:通过共享技术实现相同或相似对象的重用p 适用性p 一个应用程序使用了大量的对象p 冗余使用了大量的对象,造成了很大的存储开销享元(享元(Flyweght)模式的结构)模式的结构享元(享元(Flyweght)模式的参与者)模式的参与者p Flyweight:描述一个接口,
58、可接受并作用于外部状态p ConcreteFlyweight:实现Flyweight接口,并为内部状态增加存储空间。必须是可共享的,存储的状态必须是内部的p UnsharedConcreteFlyweight:不强制共享p FlyweightFactory:创建并管理flyweight对象;确保合理地共享flyweight,提供已创建的flyweight实例或者创建一个p Client:维持一个对flyweight的引用;计算或存储一个(多个)flyweight的外部状态享元(享元(Flyweght)模式的参与者)模式的参与者p Flyweight执行时所需的状态必定是内部或外部的。内部状态存
59、储在ConcreteFlyweight中,外部对象则由Client对象存储或计算。当用户调用flyweight对象操作时,将该状态传递给它p 用户不应直接对ConcreteFlyweight类进行实例化,而只能从FlyweightFactory对象得到ConcreteFlyweight对象,以保证对它们适当地进行共享享元(享元(Flyweght)模式的效果分析)模式的效果分析p Flyweight模式的核心就是把大量共享的对象收集在一起使用简单工厂模式进行管理,避免由于大量的小对象导致系统的内存过渡消耗p 当重复对象较多时, Flyweight模式具有较好的空间性能,但在查找搜索上消耗了时间复
60、杂度代理(代理(Proxy)模式的几个来源)模式的几个来源代理(代理(Proxy)模式的由来)模式的由来p 某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动p 如果对象是一个大图片,需要花费很长时间才能显示出来,此时需要做个图片Proxy来代替真正的图片p 如果对象在某远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,可以用Proxy来代替那个对象p 如何应对这种变化?如何提供一种机制让原本交互起来比较困难的两个对象实现畅通无阻地交流呢?如何保持系统的结构不随着需求改变而轻易改变?这就是代理模式代理(代理(Proxy)模式的意图和适用性)模式的意图和适用性p 意图:为其他对
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年采矿权出让与矿产资源储备管理合同范本3篇
- 2024年度消防安全信息公示合同2篇
- 2024年度新能源汽车电池管理系统委托加工合同3篇
- 2024全新智能交通管理系统委托开发合同3篇
- 2024年度某能源公司与光伏设备供应商签订的采购合同2篇
- 吉林体育学院《工程流体力学与传热学》2023-2024学年第一学期期末试卷
- 吉林司法警官职业学院《健康评估(一)》2023-2024学年第一学期期末试卷
- 2024年度物流服务合同的担保人规定2篇
- 2024全新商铺租赁合同终止及品牌使用许可协议3篇
- 2024年度电子商务平台软件运维与客户服务协议3篇
- 中华人民共和国学前教育法
- 自动售货机项目营销计划书
- 创先争优活动先进典型选树实施方案
- 餐饮服务电子教案 学习任务5 斟酒技能(1)-徒手斟酒
- 2024年度工作总结模板
- 汽车吊起重吊装方案
- 电商平台产品质量保障服务合同
- 铣工高级工测试题(含答案)
- 数字营销学课件 5第五章 顾客画像及应用
- 教官协作服务合同
- 【课件】2025届高三英语一轮英语备考课件
评论
0/150
提交评论