第十二章 适配器模式和外观模式 PPT课件
适配器(Adaptor)模式PPT教学课件

2020/12/10
7
类适配器简单例子
public interface Print { public abstract void printWeak(); public abstract void printStrong();
} }
2020/12/10
9
对象适配器
Client
RequiredClass ______________ requiredMethod()
ExistingClass __________ usefulMethod()
} ============================ public class Main {
public static void main(String[] args) { Print p = new PrintBanner("Hello"); p.printWeak(); p.printStrong();
2020/12/10
4
Adapter模式
Struct
class adapter
object adapter
2020/12/10
5
例子
《interface》
RocketSim getMass():double getThrust():double setSimTime(t:double)
PhysicalRocket
} -------------------------public class Banner {
深入设计模式(三)——适配器模式

深⼊设计模式(三)——适配器模式⼀、适配器设计模式介绍适配器模式,将⼀个类装换成客户期望的另外⼀个接⼝。
Adapter模式使⽤的原本由于接⼝不兼容⽽不能茉莉花物那些可以⼀起⼯作。
⼆、解决的问题1、使⽤第三⽅组件,⽽这个组件的接⼝与⽬前系统接⼝不兼容(如⽅法与系统⽅法不⼀致等),可以使⽤适配器模式解决接⼝不兼容问题。
2、使⽤早前项⽬⼀些有⽤的类,可以⽤适配器模式解决现有接⼝与原有对象接⼝不兼容问题。
三、⽣活中的例⼦适配器模式允许将⼀个类的接⼝转换成客户期望的另⼀个接⼝,使⽤原本由于接⼝不兼容⽽不能⼀起⼯作的类可以⼀起⼯作。
扳⼿提供了⼀个适配器的例⼦。
⼀个孔套在棘齿上,棘齿的每个边的尺⼨是相同的。
在美国典型的连长为1/2和1/4。
显然,如果不使⽤⼀个适配器的话,1/2的棘齿不能适合1/4的孔。
⼀个1/2到1/4的适配器具有⼀个1/2的阴槽来套上⼀个1/2的齿,同时有⼀个1/4的阳槽来卡⼊1/4的扳⼿。
四、适配器分析1.适配器模式结构2.代码1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace适配器模式8 {9///<summary>10///客户期待的接⼝或者抽象类Target11///</summary>12public abstract class Target13 {14public abstract void Request();15 }16 }客户期待的接⼝或者抽象类Target1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace适配器模式8 {9///<summary>10///要适配的类Adaptee,也就是与期望调⽤接⼝不相符的类11///</summary>12public class Adaptee13 {14public void SpecificReques() {15 Console.WriteLine("执⾏要适配类的特殊请求⽅法");16 }17 }18 }要适配的类Adaptee,也就是与期望调⽤接⼝不相符的类1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace适配器模式8 {9public class Adapter:Target10 {11private Adaptee adaptee;12public override void Request()13 {14if (adaptee == null) {15 adaptee = new Adaptee();16 }17 adaptee.SpecificReques();18 }19 }20 }适配器类Adapter,把源接⼝转换成⽬标接⼝,包⾏变量adaptee1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace适配器模式8 {9///<summary>10///适配器模式,将⼀个类装换成客户期望的另外⼀个接⼝。
适配器模式

• 想想可以解决的方法: • 写一系列的if语句来一条条的判断.但这样的写法 虽然可以实现目前的需求,可如果当税率发生了变 化你又得拿出你的程序一步一步的修改.如果if语 句的条数发生变化的话我们还必须在代码中添加 必要的if判断.这对于程序的维护来说是相当麻烦 的.如果我们使用职责链模式的话就可以相当简单 了. • 先说说我们的设计思想. • 我们可以采用职责链完成所得税的计算,由职责链 上的一个对象负责计算某一段的所得税.如果符合 计算条件,则计算;否则由下一个对象计算.
• 责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每 一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传 递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端 并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不 影响客户端的情况下动态地重新组织链和分配责任。
• • •
责任链模式和状态模式的异同
• 职责链模式:当客户提交一个请求时,请求是沿链传递直至有一个 ConcreteHander对象负责处理它。接收者和发送者都没有对方的明 确信息,且链中的对象自己并不知道链的结构,在运行时自动确定。 结果是职责链可简化对象的相互连接,它们仅需保持一个指向其后继 者的引用或指针,而不需要保持它所有的候选接受者。这也就大大降 低了耦合度了。也就是说,我们可以随时地增加或修改处理一个请求 的结构。增强了给对象指派职责的灵活性。 • 状态模式:状态模式主要解决的是当控制一个对象状态转换的条件表 达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系 列类当中,可以把复杂的判断逻辑简化。状态模式将与特定状态相关 的行为局部化,并且将不同状态的行为分割开来。即将特定的状态相 关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某 个ConcreteState中,所以通过定义新的子类可以很容易地增加新的 状态和转换。这样做的目的是为了消除庞大的条件分支语句。状态模 式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间 的依赖。
10.设计模式.适配器模式(Adapter)

武汉科技大学
适配器模式(Adapter)
static void Main(string[] args) { Player pp = new Forwards("Patrick Patterson"); pp.Attack(); Player tw = new Guards("Terrence Williams"); tw.Attack(); ForeignCenter ym = new ForeignCenter("姚明"); ym.进攻(); } Console.Read();
球员
+Attack() +Defense()
前锋 +Attack() +Defense()
中锋 +Attack() +Defense()
后卫 +Attack() +Defense()
外籍中锋 +进攻() +防守()
武汉科技大学
问题(Problem) 火箭教练的指挥
Patrick Patterson, Attack(前锋 帕特里克-帕特森) Terrence Williams, Attack(后卫 泰伦斯-威廉姆斯) Yao Ming,Attack (中锋 姚明)
武汉科技大学
适配器模式(Adapter) 类适配器和对象适配器
假设我们在软件开发中要记录日志,包括数据ቤተ መጻሕፍቲ ባይዱ记录日志 DatabaseLog和文本文件记录日志WriteLog
武汉科技大学
适配器模式(Adapter) 类适配器和对象适配器
武汉科技大学
适配器模式(Adapter)
C++之适配器设计模式和外观模式

所谓建造者设计模式是指将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式的优点:1、建造者独立,易于扩展。
2、便于控制细节风险。
建造者模式缺点:1、产品必须有共同点,范围有限制。
2、如果内部变化复杂,将会有很多建造类。
适用场景:1、需要生成的对象具有复杂的结构。
2、需要生成的对象内部属性本身相互依赖。
代码实现:比如联想有众多型号的电脑,比如ThinkPad 和 Yoga,它们结构基本一致,都是由CPU,主板、内存、显卡等组成。
如果为每台电脑单独设计一套组装流程,管理成本太高,用建造者设计模式可以为它们设计一个统一的组装流程。
创建产品我们需要一个 Computer 类,它可以通过组装零件来创建。
// product.h#ifndef PRODUCT_H#define PRODUCT_H#include <iostream>using namespace std;// 电脑class Computer{public:void SetmCpu(string cpu) { m_strCpu = cpu;}void SetmMainboard(string mainboard) { m_strMainboard = mainboard; }void SetmRam(string ram) { m_strRam = ram; }void SetVideoCard(string videoCard) { m_strVideoCard = videoCard; } string GetCPU() { return m_strCpu; }string GetMainboard() { return m_strMainboard; }string GetRam() { return m_strRam; }string GetVideoCard() { return m_strVideoCard; }private:string m_strCpu; // CPUstring m_strMainboard; // 主板string m_strRam; // 内存string m_strVideoCard; // 显卡};#endif // PRODUCT_H创建抽象建造者产品类准备好以后,就可以创建 Builder 了,Builder 提供的功能用于创建电脑的各个部件。
适配器模式培训教学课件下载(PPT38张)

Adaptee
+ specificRequest () ...
Adapter
adaptee
+ request () ...
adaptee.specificRequest();
适配器模式
模式结构
✓ 适配器模式包含如下角色: • Target:目标抽象类 • Adapter:适配器类 • Adaptee:适配者类 • Client:客户类
• 参考代码 (Chapter 10 Adapter\sample01)
演示……
适配器模式
适配器模式实例与解析
✓ 实例二:加密适配器 • 某系统需要提供一个加密模块,将用户信息(如密码 等机密信息)加密之后再存储在数据库中,系统已经 定义好了数据库操作类。为了提高开发效率,现需要 重用已有的加密算法,这些算法封装在一些由第三方 提供的类中,有些甚至没有源代码。使用适配器模式 设计该加密模块,实现在不修改现有类的基础上重用 第三方加密方法。
功能更为强大的结构。 装饰模式(Decorator)
桥接模式(Bridge)
适包配装器 器模(W式rap(Ap✓dear)p。Ater dPataterpn) :t将e一r个P接a口转tt换e成r客n户希: 望C的o另一n个v接e口r,t适t配h器模e式i使n接t口e不r兼f容a的c那e些类o可f以a一起c工l作a,s其s别名为
演示……
适配器模式
模式优缺点
✓ 适配器模式的优点
• 将目标类和适配者类解耦,通过引入一个适配器类来重用现有 的适配者类,而无须修改原有代码。
• 增加了类的透明性和复用性,将具体的实现封装在适配者类中, 对于客户端类来说是透明的,而且提高了适配者的复用性。
外观模式ppt较完整版

外观模式
• 模式优缺点
– 外观模式的优点
• 对客户屏蔽子系统组件,减少了客户处理的对象数目 并使得子系统使用起来更加容易。同时,客户代码变 简单 • 实现了子系统与客户之间的松耦合关系。
外观模式
• 模式优缺点
– 外观模式的优点
• 降低了大型软件系统中的编译依赖性,并简化了系 统在不同平台之间的移植过程。 • 只是提供了一个访问子系统的统一入口,并不影响 用户直接使用子系统类。
外观模式
• 模式扩展注意
– 不要试图通过外观类为子系统增加新行为
• 不要通过继承一个外观类在子系统中加入新的行为, 这种做法是错误的。 • 外观模式的用意:为子系统提供一个集中化和简化的 沟通渠道
外观模式
• 模式扩展
– 外观模式与迪米特法则
• 外观模式创造出一个外观对象,将客户端所涉及的属 于一个子系统的协作伙伴的数量减到最少,使得客户 端与子系统内部的对象的相互作用被外观对象所取代。 • 外观模式就是实现代码重构以便达到“迪米特法则” 要求的一个强有力的武器。
• 当要为一个复杂子系统提供一个简单接口时可以使用 外观模式。 • 客户程序与多个子系统之间存在很大的依赖性。 • 在层次化结构中,可以使用外观模式定义系统中每一 层的入口,层与层之间不直接产生联系,而通过外观 类建立联系,降低层之间的耦合度。
外观模式
• 模式扩展
– 一个系统有多个外观类 • 在外观模式中,通常只需要一个外观类,并且此外观类只有一 个实例,换言之它是一个单例类。在很多情况下为了节约系统 资源,一般将外观类设计为单例类。当然这并不意味着在整个 系统里只能有一个外观类,在一个系统中可以设计多个外观类, 每个外观类都负责和一些特定的子系统交互,向用户提供相应 的业务功能。
第12适配器模式和外观模式PPT优秀课件

8
客户使用适配器过程
① 客户通过目标接口调用适配器的方法对适配器发出请求。
② 适配器使用被适配者接口把请求转换成被适配者的一
个或多个调用接口。
③ 客户收到调用结果,但并未察觉这一切是适配器在起
转换作用。
客户和被适配者是解 耦的。
9
适配器模式定义
适配器模式将一个类的接口转换成客户
期望的另一个接口。适配器让原本不兼容的 类可以合作无间。
}
}
}
5
测试适配器
public class DuckTestDrive { public static void main(String[] args) {
火鸡包装进火鸡 适配器中,使它 看起来象一只鸭
MallardDuck duck = new MallardDuck();
子。
WildTurkey turkey = new WildTurkey();
}
火鸡不会呱呱叫, 只会咯咯叫。火 鸡也会飞,虽然
飞不远。
public class WildTurkey implements Turkey { public void gobble() { System.out.println("Gobble gobble");
火鸡的一 个具体实
现。
}
public void fly() {
Tuner
am plifier
on() off() setA m() s et F m () setFrequency () t o St r in g( )
Screen
up () dow n() t o St r in g( )
爆米花机 P o pc o r m P o ppe r on() off() p op () t o St r in g( )
适配器模式

} }
public class Client { public static void Main(string[] args) { // Create adapter and place a request Target t = new Adapter(); t.Request(); } }
适配器模式的两Biblioteka 形式适配器模式有类的适配器模式和对象的适 配器模式两种
类的Adapter模式的结构:
Adaptee类没有Request方法,而客户期待这个方法.为了使客户 能够使用Adaptee类,提供一个中间环节,即类Adapter类, Adapter类实现了Target接口,并继承自Adaptee,Adapter类的 Request方法重新封装了Adaptee的SpecificRequest方法,实现了 适配的目的. 因为Adapter与Adaptee是继承的关系,所以这决定了这个适配 与 是继承的关系, 因为 是继承的关系 器模式是类的.
该适配器模式所涉及的角色包括
目标(Target)角色:这是客户所期待的接 口.目标可以是具体的或抽象的类,也可 以是接口. 源(Adaptee)角色:需要适配的类. 适配器(Adapter)角色:通过在内部包装 (Wrap)一个Adaptee对象,把源接口转 换成目标接口.
class Target { // Methods virtual public void Request() { // Normal implementation goes here } } // "Adaptee" class Adaptee { // Methods public void SpecificRequest() { Console.WriteLine("Called SpecificRequest()" ); } }
设计模式之适配器模式与外观模式(二)

设计模式之适配器模式与外观模式(二)好了,通过上次的学习,我们已经知道适配器模式是如何将一个类的接口转换成另一个符合客户期望的接口。
同时也知道在Java中要做到这一点,必须将一个不兼容接口的对象包装起来,变成兼容的对象。
我们现在要看一个改变接口的新模式,但是它改变接口的原因是为了简化接口。
这个模式被巧妙地命名为外观模式(Facade-Pattern),之所以这么称呼,是因为它将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外观。
繁琐的看电影步骤还记得我们之前说过的命令模式中,一个遥控器能控制很多家电的过程吧。
简单的开关我们都会,复杂的模式,就比较麻烦,比如看电影的步骤:1.打开爆米花机2.开始爆米花3.将灯光调暗4.放下屏幕5.打开投影机6.将投影机的输入切换到DVD7.将投影机设置在宽屏模式8.打开功放9.将功放的输入设置为DVD10.将攻放设置为环绕立体声11.将攻放音量调到中12.打开DVD播放器13.开始播放DVD看一个电影,真的是如此繁琐。
而且看完电影之后,还得过去把这些步骤都关闭。
是用你的家庭影院竟然变得如此复杂!让我们看看外观模式如何解决这团混乱,好让你轻松享受。
灯光、相机、外观!你需要的正是一个外观:有了外观模式,通过实现一个提供更合理的接口的外观类,你可以将一个复杂的子系统变得容易使用。
1.我们为家庭影院系统创建一个外观,命名为HomeTheaterFacade,它对外暴露出几个简单的方法,例如watchMovie()2.这个外观类将家庭影院诸多组件视为一个子系统,通过调用这个子系统,来实现watchMovie()方法3.现在,你的客户代码可以调用此家庭影院外观所提供的方法,而不必再调用这个子系统的方法。
4.外观只是提供你更直接的操作,并未将原来的子系统阻隔起来。
如果你需要子系统类的更高层的功能呢,还是可以使用原来的子系统的构造家庭影院外观好了,那接下来就到实战阶段啦。
设计模式之适配器模式

设计模式之适配器模式设计模式是软件开发中常用的解决方案,它提供了一种被广泛认可的、可重用的解决方案模板。
一种常用的设计模式是适配器模式,它用于将一个类的接口转换成客户端所期待的另一种接口。
本文将介绍适配器模式的概念、应用场景和实现方法。
一、概述适配器模式是一种结构型设计模式,它允许不兼容的接口之间进行协同工作。
适配器通过包装已有的类,将现有的接口转换成客户端所期待的接口,使得原本由于接口不兼容而无法工作的类可以一起协同工作。
适配器模式通常用于以下几种情况:1. 需要使用一个已经存在的类,但其接口与所需接口不一致。
2. 需要创建一个可复用的类,该类可与多个不相关的或不可预见的类一起工作。
二、应用场景适配器模式在实际应用中具有广泛的应用场景,以下是几个常见的应用场景:1. 与第三方库的集成当我们使用第三方库时,其提供的接口可能与我们当前系统的接口不兼容,此时可以使用适配器模式来将第三方库的接口转换成我们需要的接口。
2. 兼容性问题当我们需要更新或迁移系统时,可能需要进行接口的变更,这时适配器模式可以用来保持旧的接口兼容性,同时实现新的接口。
3. 数据格式转换在数据处理过程中,可能会面临不同格式的数据,适配器模式可以用来实现不同格式的数据之间的转换,使得系统能够更好地处理数据。
三、实现方法适配器模式可以通过类适配器和对象适配器两种方式来实现。
1. 类适配器类适配器使用多重继承来实现适配器功能。
它继承了原始类,并实现了目标接口。
通过在适配器类中调用原始类的方法来实现接口的转换。
2. 对象适配器对象适配器使用组合来实现适配器功能。
它持有原始类的实例,并实现了目标接口。
通过调用原始类实例的方法来实现接口的转换。
四、示例代码下面是一个使用对象适配器实现适配器模式的示例代码:```java// 目标接口interface Target {void request();}// 原始类class Adaptee {void specificRequest() {System.out.println("Adaptee specificRequest");}}// 适配器类class Adapter implements Target {private Adaptee adaptee;Adapter(Adaptee adaptee) {this.adaptee = adaptee;}public void request() {adaptee.specificRequest();}}// 客户端使用class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new Adapter(adaptee);target.request();}}```在上述代码中,通过适配器类Adapter将原始类Adaptee的接口转换成目标接口Target,从而实现了不兼容接口之间的协同工作。
适配器模式Adapter

ILogAdaptee +WriteLog()
DataBaseLog
FileLog
新的日志记录工具类结构图
新的日志记录类主要实现代码
public abstract class LogAdaptee { public abstract void WriteLog();} public class DatabaseLog : LogAdaptee { public override void WriteLog() {Console.WriteLine("Called WriteLog Method"); }
复用、类库迁移等方面非常有用!
2.GoF23定义两种Adapter模式的实现结构:对象适配器
参见课本图12-6 类适配器模式, 和类适配器。但类适配器采用“多继承”实现方式,带
来不良的高耦合,不推荐使用。对象适配器采用“对象
组合”方式,更符合松耦合精神。
并写出其实现代码
3.Adapter模式本身要求尽可能地使用“面向接口的编程 ”风格,这样才能在后期很方便地适配!
客户期待的借口,可以是具体类或
Client Target +Request()
抽象类、接口!
Adapee +SpecificRequest()
需要适配的类 在其内部包含一个Adaptee对象,
把源接口转换成目标接口
参见课本图12-5
模式角色
•目标(Target)角色:所期待的接口,可以是接口 的或抽象类. •源(Adaptee)角色:现有的需要适配的接口. •适配器(Adapter)角色:本模式的核心,把源接口 转换成目标接口,这一角色必须是具体类!
•当软件开发进行到一半时,处于某种原因不能继续使用
适配器模式

适配器模式(Adapter Pattern)以下内容是我和小组的兄弟学习设计模式我做的课件,我整理出来和大家分享,有不妥之处敬请指出.上次做的桥接模式(Bridge),这次是适配器模式(Adapter).概述:在软件开发过程中,我们要经常要复用我们以前开发的一些“现存对象”,但是这些“现存对象”并不能满足我们新的应用环境。
怎样才能良好的复用这些对象,以满足我们的应用环境,这就是适配器(Adapter)所要解决的问题。
意图:将一个类的接口转换成客户希望的另外一个接口。
Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
——《设计模式》GOF生活中的例子:在现实生活中,像这种适配器我们经常见到,而且还是经常使用它,如:手机(深信大家都见过),我们手机在充电的时候,不可能直接在220V电源上直接充电,而是手机“充电器”进行转换成手机需要的电压才可以正常充电,否则就不可以完成充电,这个“充电器”就起到了适配的作用。
1.类的Adapter模式结构图类结构图:代码实现:1namespace Adapter_Pattern2{3public interface ITarget4 {5void GetPower();6 }7///<summary>8/// 220V电源类;9///</summary>10public class Power11 {12///<summary>13///从电源中得到220V的电压; 14///</summary>15public void GetPoer220V()1718 }19 }20///<summary>21///适配器类(充电器);22///</summary>23public class Adapter : Power, ITarget24 {25///<summary>26///得到想要电压;27///</summary>28public void GetPower()29 {30this.GetPoer220V();31 Console.WriteLine("得到手机的充电电压!");32 }33 }客户端调用:1namespace Adapter_Pattern2{3class Program4 {5///<summary>6///这里相当于是手机;7///</summary>8///<param name="args"></param>9static void Main(string[] args)10 {11 Console.Write("手机:");12 ITarget Target = new Adapter();13 Target.GetPower();14 Console.Read();16 }17}特点:它使用多继承的方式来实现,我们只需要调用得到电压(GetPower())方法,由充电器(Adapter)去将220V的电压转成我们需要的电压供我们使用。
设计模式学习--适配器模式(Adapter Pattern)+外观模式

@Override public void quack() { //实现接口中的方法 turkey.gobble(); //用适配对象来转换需要实现的功能 }
}
被适配对象接口具体实现类
package ducks;
/** * * @author wwj * 火鸡具体实现类 */
public class WildTurkey implements Turkey {
@Override public void gobble() { System.out.println("Gobble gobble"); }
目标接口具体实现类 package ducks;
/** * *@author wwj *适配器模式:绿头鸭实现类 * */
public class MallardDuck implements Duck {
@Override public void quack() { System.out.println("Quack"); }
}Hale Waihona Puke 适配器模式测试结果The Turkey says... Gobble gobble I'm flying a short distance
The Duck says... Quack I'm flying
The TurkeyAdapter says... Gobble gobble I'm flying a short distance I'm flying a short distance I'm flying a short distance I'm flying a short distance I'm flying a short distance
结构型设计模式

结构型设计模式结构型设计模式包括:适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式。
1、适配器模式当需要使⽤⼀个现存的类,但它提供的接⼝与我们系统的接⼝不兼容,⽽我们还不能修改它时,我们可以将⽬标类⽤⼀个新类包装⼀下,使新类的接⼝保留原接⼝模式,但实际上使⽤的是⽬标类的接⼝。
⽐如我们系统中原来的⽇志接⼝为MyFactory,现在要使⽤新的⽇志库NewFactory,其写⽇志的接⼝与我们原来的接⼝不同,但我们⽆法修改新⽇志库的代码,所以可以包装⼀下新的⽇志库类来使⽤://原来的⽇志接⼝public interface MyFactory {void log(String tag, String message);}//新的⽇志接⼝public interface NewLogger {void debug(int priority, String message, Object ... obj);}public class NewLoggerImp implements NewLogger {@Overridepublic void debug(int priority, String message) {}}//⽇志适配器类public class LogAdapter implements MyFactory {private NewLogger nLogger;public LogAdapter() {this.nLogger = new NewLoggerImp();}@Overridepublic void log(String tag, String message) {Objects.requireNonNull(nLogger);nLogger.debug(1, message);}}View Code2、桥接模式现在有⼀个形状类Shape,其⼦类有圆形Circle和⽅形Square,如果我们想要扩展⼦类使其包含颜⾊的话,可以增加红⾊圆形孙⼦类、蓝⾊圆形孙⼦类和红⾊⽅形孙⼦类、蓝⾊⽅形孙⼦类,如下图所⽰。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
on() off() dim() toString()
DvdPl ayer
amplifier
on() off() ejet() p ause() p lay () setSurroundAudio() setTwoChannelAudio() st op ()
有很多类, 很多交互,
DvdPlayer amp lifier on() off() ejet() p ause() p lay () ...
Projector dvdPlay er on() off() tvM ode() wideScreen() toString()
喜欢自己操 作这些组件!
15
简化外观(续)
子系统外观 的客户端。
Client
Target request()
Adaptee specificRequest()
对象适配器可适配某个 类及其子类。但是,需 要实现被适配者,多一 个对象,效率低点。
Adapter request()
类适配器不是 使用组合来适 配被适配者, 而是继承被适 配者和目标类。
11
家庭影院
调谐器
}
火鸡不会呱呱叫, 只会咯咯叫。火 鸡也会飞,虽然
飞不远。
public class WildTurkey implements Turkey { public void gobble() { System.out.println("Gobble gobble");
火鸡的一 个具体实
现。
}
public void fly() {
tuner dvdPlay er cdPlay er
on() off() setCd() setDvd() setStereoSound() setSurroundSound() ...
CdP l ayer
amplifier
on() off() ejet() p ause() p lay () st op () toString()
还有一大群
接口。
Projector
dvdPlayer
on() off() tvM ode() wideScreenM ode() toString()
12
观赏电影
⑴ 打开爆米花机 ⑵ 开始爆米花 ⑶ 灯光调暗
看完还得一 个个关掉!
⑷ 放下屏幕
⑸ 打开投影机
⑹ 将投影机的输入切换到DVD
⑺ 将投影机切换到宽屏方式
this.amp = amp; this.tuner = tuner; this.dvd = dvd; this.cd = cd; this.projector = projector; this.screen = screen; this.lights = lights; this.popper = popper; } // 其它方法 }
HomeTheaterFacade
watchMovie()
endMovie()
listenToCd()
endCd()
listenToRadio()
endRadio()
外观要 简化的 子系统。
Tuner amp lifier on() off() setAm() setFm() ...
S creen up () down() toString()
PopcormPopper on() off() toString()
Amplifier tuner dvdPlay er cdPlay er on() off() setCd() setDvd() ...
CdPlayer amp lifier
on() off() ejet() ...
TheaterLights on() off() ...
外观子系统中每一个 组件的引用都传入它 的构造器中。然后, 外观把它们赋值给相
应的实例变量。
18
实现简化的接口
public void watchMovie(String movie) { System.out.println("Get ready to watch a movie..."); popper.on();
客户代码可以调用家庭影院 外观所提供的方法,不必调 用这个子系统的方法。要想 看电影,只要调用一个方法 (watchMovie())就可以了。
外观只是提供更直接 的操作,并未将原来 的子系统阻隔起来。 如果需要子系统类的 更高层功能,还可以 使用原来的子系统。
16
构造家庭影院的外观
public class HomeTheaterFacade {
public HomeTheaterFacade(Amplifier amp, // 构造方法 Tuner tuner, DvdPlayer dvd, CdPlayer cd, Projector projector, Screen screen, TheaterLights lights, PopcornPopper popper) {
screen.down(); // 放下屏幕
projector.on();
projector.setInput(dvd);
打开投影机,设置为DVD和宽屏模式…
projector.wideScreenMode();
amp.on();
amp.setDvd(dvd);
打开功放,设置为DVD,调整成
amp.setSurroundSound(); 环绕立体声模式,音量调到5…
Tuner
amplifier
on() off() setAm() setFm() set Frequency () toString()
Screen
up () down() toString()
爆米花机 PopcormPopper on() off() p op () toString()
放大器
Ampl i fi er
测试鸭子。
System.out.println("\nThe TurkeyAdapter says...");
testDuck(turkeyAdapter);
}
static void testDuck(Duck duck) {
测试适配器:传
duck.quack(); duck.fly();
入一个假装鸭子 的火鸡。
⑻ 打开功放
⑼ 将功放输入设置为DVD
⑽ 将功放设置为环绕立体声
⑾ 将功放音量调到中(5)
⑿ 打开DVD播放器
⒀ 开始播放DVD
开这么多东西, 太累啦!
13
开机任务写成类和方法调用
popper.on(); 打开爆米花机,开始爆米花 popper.pop();
lights.dim(10); // 灯光调暗
第十二章 适配器模式和外观模式
适配器
欧洲壁式插座
交流适配器 美国标准交流电插头
适转配换器成将另一一种种接接口口。
1
面向对象适配器
现系 有统 的
厂 商 类
两个接口无法匹配, 所以无法工作。
现系 有统 的
适厂 配商 器类
不需改变代码 新代码 不需改变代码
现系 有统 的
适
厂
配
商
器
类
这个适配器实现了 所期望类的接口。
而且这个适配器也能 和厂商类的接口沟通。
2
适配鸭子的火鸡
public interface Duck { public void quack(); public void fly();
鸭子接口,具 备呱呱叫和飞
行能力。
}
public class MallardDuck implements Duck {
Duck turkeyAdapter = new TurkeyAdapter(turkey);
System.out.println("The Turkey says...");
turkey.gobble(); turkey.fly();
测试火鸡。
System.out.println("\nThe Duck says..."); testDuck(duck);
System.out.println("I'm flying a short distance");
}
}
4
火鸡适配器
假定缺鸭子对象,用火鸡对象来冒充,需要为火鸡对
象写一个适配器。
public class TurkeyAdapter implements Duck {
Turkey turkey; public TurkeyAdapter(TurktVolume(5);
dvd.on(); dvd.play(movie);
打开DVD播放机。
14
创建一个HomeTheaterFacade
watchMovie()
的新类,它对外有几个简单 的方法。
这个外观将家庭影院的诸 多组件视为一个子系统,
外观
通过调用这个子系统,来
简化外观
实现watchMovie()方法。
Client
客户只看到 目标接口。
<<interface>>
Target request()
适配器实现 目标接口。
Adapter request()
被适适配配器者组。合
Adaptee specificRequest()
所有的请求都委 托给被适配者。
类图
10
对象和类适配器
有两种适配器:对象适配器和类适配器。前一页是对 象适配器类图,类适配器类图如下: