软件工程
第六章 结构型设计模式
软件工程
OO的基本概念(抽象,封装,继承,多态),九个oo原 则。千万不要轻视这些原则,因为每个设计模式背后都包 含了几个OO原则的概念。很多时候,在设计时有两难的情 况,这时候我们必须回归到OO原则,以方便判断取舍。可 以这么说:OO原则是我们的目标,而设计模式是我们的做 法。 使用模式最好的方式是:“把模式装进脑子里,然 后在你得设计和已有的应用中,寻找何处可以使用它们。” 以往是代码复用,现在是经验复用。 记住。知道抽象、继承、多态、这些概念,并不会 马上让你变成好的面向对象设计者。设计大师关心的是建 立弹性的设计,可以维护,可以应付改变,
返回目录
软件工程
结构性模式关注于如何将类和对象组合成更大的结构。结构 性类模式使用继承来组合接口或实现。 Adapter是一个接口(Adaptee)与另一个接口一致,从而为 不同的接口提供统一的抽象形式。类Adapter模式通过Adaptee 类中私有继承来实现这一点。接着,Adapter以Adaptee的接口 来表达自己的接口。除了组合接口或实现,结构性对象模式提 供通过组合对象来实现新功能的方法。对象组合的额外灵活性 来自于在运行时改变组合的能力。而这一点是静态类组合无法 做到的。
返回目录
软件工程
Composite是结构性对象模式的一个例子。它描述了如何由 代表两种对象:基本对象和合成对象的类来建立类层次结构。 合成对象可以用基本对象和其它的合成对象来组合成任意复杂 的结构。 在Proxy模式中,Proxy对象作为其他对象的一个方便的代理 或占位符。可以通过许多方法来使用。可以作为远程对象的本 地表示;可以表示“按需装载”的大型对象;可以对敏感对象 提 供受限访问。Proxy为对象的某些特性提供了间接层,从而他 们可以限制、优化或改变特性。
返回目录
软件工程
Flyweight为共享对象定义一种结构。对象共享至少存在两 个理由:效率和一致性。 Flyweight因空间效率而关注共享。使用大量对象的应用必须仔 细地考虑对象的开销。采用共享对象而非复制可以节省大量的空 间。但仅在对象无相关于上下文的状态时,才能被共享。 Flyweight对象不包含上述状态。任何完成功能所需的附加 信息在需要时被传递给它们。在不存在相关于上下文的状 态时,Flyweight对象能被自由地共享。 Decorator描述了如何给对象动态地增加责任。Decorator是一种 递归组合对象的结构性模式,它允许无限制地增加职责。 例如: 包含了组件接口的Decorator对象可以提供如边框、阴影等修 饰。可以简单地通过链接两个Decorator对象来为组件增加两个 修饰(功能),依次类推可以增加更多职责
。返回目录
软件工程
目录 6.1 适配器模式 6.2 装饰模式 6.3 桥接模式 6.4 享元模式 6.5 外观模式 6.6 代理模式 6.7 组合模式返回目录
软件工程
6.1 适配器(Adapter)模式一.适配器模式的由来 二.适配器模式的意图和适用性 三.适配器模式结构及参与者 四.应用举例 五.效果分析
返回目录
软件工程
6.1.1 适配器模式的由来 Adapter模式解决的问题在生活中经常会遇到:比如我们有一个team为外界提供S类服务,但是我们team里面没有能够 完成此项任务的member,然后我们得知有A可以完成这项服 务。为了保证我们对外的服务类别的一致性(提供S服务), 我们有以下两种方式解决这个问题:
1)把A直接兼并到我们team为我们工作,提供S服务的时候让 A去办就是了;2)A可能在别的地方有工作,并且不准备接受我们的兼并,于 是我们team可以想这样一种方式解决问题:我们安排B去完成这 项任务,并让B做好A的工作,让B工作的时候可以向A请教,因 此B就是一个复合体(提供S服务,但是是A的继承弟子)。返回目录
软件工程
6.1.1 适配器模式的由来 Adapter模式用途 实际上在软件系统设计和开发中,这种问题会经 常遇到:我们为了完成某项工作购买了一个第三 方的库来加快开发。这就带来了一个问题:我们 在应用程序中已经设计好了功能接口,与这个第 三方提供的接口不一致,为了使得这些接口不兼 容的类(不能在一起工作)可以在一起工作, Adapter模式提供了将一个类(第三方库)的接口 转化为客户(购买使用者)希望的接口。返回目录
软件工程
6.1.2 适配器模式意图和适用性将一个类的接口转换成客户希望的另外一个接口。Adapter模式。使得原本由 于接口不兼容而不能一起工作的那些类可以一起工作。 有两类适配器模式:
对象适配器模式 - 在这种适配器模式中,适配器容纳一个它我包裹的类的 实例。在这种情况下,适配器调用被包裹对象的物理实体。对象适配器” 通过组合除了满足“用户期待接口”还降低了代码间的不良耦合。在工作 中推荐使用“对象适配”。 类适配器模式 - 这种适配器模式下,适配器继承自已实现的类(一般多重 继承)。当客户在接口中定义了他期望的行为时,我们就可以应用适配器 模式,提供一个实现该接口的类,并且扩展已有的类,通过创建子类来实 现适配。返回目录
软件工程
6.1.2 适配器模式意图和适用性 你想使用一个已经存在的类,而它的接口不符合你的 要求。 你想创建一个可以复用的类,该类可以与其他不相关 的类或不可预见的类(即那些接口可能不一定兼容的 类)协同工作。 (仅适用于对象Adapter)你想使用一些已
经存在的子 类,但是不可能对每一个都进行子类化以匹配它们的 接口。对象适配器可以适配它的父类接口。 适配器模式分为类模式适配器和对象模式适配器。返回目录
软件工程
你可能会经常遇到下面这种情况,厂家提供的接口和你写的接口合不上,怎么办? 这时候你不想改变自己的接口来适应厂家的接口,同时你又不能改变厂家的接口,那么 这个时候你就应该考虑使用适配器模式了。厂家调用他们的接口,而实际上我们给的却 是看似像厂家的接口的接口。
通过上图我想大家应该很清楚了吧,这个模式很简单的。但是却是很有用的。
返回目录
软件工程
把一个类的接口变换成客户端所期望的另一种 接口,从而使原本因接口不匹配而无法在一起 工作的两个类能够工作在一起。
返回目录
软件工程
6.1 适配器模式 6.1.2 角色及其职责(1) Client所使用的与特定领域相关的接口。即被客户端Client访问 并对适配器类Adapter进行抽象。Client Target +Request () Adaptee +SpecificRequest ()
目标角色(Target)
源角色 (Adaptee ) 需要适配的接口类,即被适配者, 客户端Client的请求委托给 Adaptee完成。 适配器角色( Adapter ) 适配器,负责Adaptee的接口与 Target接口进行适配。 客户端(Client)
Adapter +Request ()
继承关系
类适配器结构图
与符合Target接口的对象协同的类。 客户端Client只能访问目标接口 返回目录 Target。
软件工程
6.1 适配器模式 6.1.2 角色及其职责(2) Client所使用的与特定领域相关的接口。即被客户端Client访问 并对适配器类Adapter进行抽象。Client Target +Request () Adaptee +SpecificRequest ()
目标角色(Target)
源角色 (Adaptee ) 需要适配的接口类,即被适配者, 客户端Client的请求委托给 Adaptee完成。 适配器角色( Adapter ) 适配器,负责Adaptee的接口与 Target接口进行适配。 客户端(Client)
Adapter +Request ()
引用关系
对象适配器结构图
与符合Target接口的对象协同的类。 客户端Client只能访问目标接口 返回目录 Target。
软件工程
6.1 适配器模式 6.1.3 核心实现代码(1)Adaptee +SpecificRequest ()
Client
Target +Request ()
public interface Target { class Adaptee public Request (); { } public SpecificRequest ( ) { … } } class Adapter : Target , Adaptee { public Request ()
Adapter
继承关系
+Request ()
{类适配器结构图 }
…}
返回目录
软件工程
6.1 适配器模式 6.1.3 核心实现代码(2)Adaptee +SpecificRequest ()
Client
Target +Request ()
public interface Target { class Adaptee public Request () { { public SpecificRequest ( ) … { } … } } } class Adapter : Target { private Adaptee adaptee; public Request ()
Adapter
引用关系
+Request ()
对象适配器结构图 }
{ … }
返回
目录
软件工程
例如,如图所示某信息系统的总体体系结构图,其中“三维图形处理组件”是外包开发, 该组件接着版本升级可能发生改变。由于接口变化将会引起客户端多处发生改变,使系 统的升级时成本很高,可维护性大幅降低。 可以使用设配器模式来屏蔽接口的变化, 如下图所示。
可以使用设配器模式来屏蔽接口的变化,如下图所示。
返回目录
软件工程
6.1.5 效果分析对于类适配器: 1.用一个具体的Adapter类对Adaptee和Taget进行匹配。结果是当 我们想要匹配一个类以及所有它的子类时,类Adapter将不能胜任 工作。 2.使得Adapter可以重定义Adaptee的部分行为,因为Adapter是 Adaptee的一个子类。 3.仅仅引入了一个对象,并不需要额外的指针一间接得到Adaptee. 对于对象适配器: 1.允许一个Adapter与多个Adaptee,即Adaptee本身以及它的所有 子类(如果有子类的话)同时工作。Adapter也可以一次给所有的 Adaptee添加功能。 2.使得重定义Adaptee的行为比较困难。这就需要生成Adaptee的 子类并且使得Adapter引用这个子类而不是引用Adaptee本身。返回目录
软件工程
优点:方便设计者可以自由定义接口,而不用担 心匹配的问题。 缺点:属于静态结构 ,由于只能单继承,所以 不适用于多种不同的源适配到同一个目标。 如果仅仅讲“如何实现适配器”那很简单,但要 解释“为什么用、什么时候用适配器模式”就有 点难度 通过运用Adapter模式,就可以充分享受进行类 库迁移、类库重用所带来的乐趣。 。返回目录
软件工程
6.2 装饰(Decorator)模式一.装饰模式的由来 二.装饰模式意图及适用性 三.装饰模式结构和参与者 四.应用举例 五.效果分析
返回目录