当前位置:文档之家› 第9讲 适配器模式

第9讲 适配器模式


火鸡适配器包装 了一个火鸡对象, 同时实现了鸭子 接口。这样就可 以像使用鸭子一 样使用火鸡了。
使用适配器
public class DuckTestDrive { public static void main(String[] args) { MallardDuck duck = new MallardDuck(); WildTurkey turkey = new WildTurkey(); Duck turkeyAdapter = new TurkeyAdapter(turkey); System.out.println("火鸡说..."); turkey.gobble(); 在需要鸭子对象 turkey.fly(); 的地方使用了火 System.out.println("\n鸭子说..."); System.out.println("\n ..."); 鸡适配器对象, testDuck(duck); 火鸡适配器对象 System.out.println("\n火鸡适配器说..."); 包装了一个火鸡 testDuck(turkeyAdapter); 对象,所以实际 } 使用的是火鸡对 static void testDuck(Duck duck) { 象。 duck.quack(); duck.fly(); } } 需要使用鸭子对象
分析
WebFormDesigner在本例中是Adaptee, WebFormDesigner_text_actionAdapter在本例中是Adapter, java.awt.event.ActionListener在本例中是适配目标。 适配目标为一接口,代码如下: public interface ActionListener extends EventListener { /** * Invoked when an action occurs. */ public void actionPerformed(ActionEvent e); } 适配目标中只有一个方法:actionPerformed()。由于 WebFormDesigner_text_actionAdapter 实现了 java.awt.event.ActionListener,所以要求实现actionPerformed()方法。 WebFormDesigner_text_actionAdapter实现actionPerformed()方法是引 用了WebFormDesigner这个adaptee来完成的。从代码中可以看出, WebFormDesigner是WebFormDesigner_text_actionAdapter的方法的参数, 所以WebFormDesigner_text_actionAdapter依赖WebFormDesigner。 Adaptee类(WebFormDesigner)的方法(text_actionPerformed)与Adapter 类(WebFormDesigner_text_actionAdapte)的方法(actionPerformed) 不同名而实现相同功能,这就是我们上面分析的基于对象的Adapter模式。
基于类的Adapter模式
基于类的Adapter模式的一般结构如下: Adaptee类为Adapter的父类,Adaptee类 为适配源,适配目标(接口)也是 Adapter的父类;基于类的Adapter模式 比较适合应用于Adapter想修改Adaptee 的部分方法的情况。
基于对象的Adapter模式
Adapter模式
定义
将一个类的接口转换成客户端所期望的另一 种接口,从而使原本因接口不匹配而无法在 一起工作的两个类能够在一起工作。
别名
包装器Wrapper
Adapter模式
动机
有时,为复用而设计的工具箱类不能够被复用的原 因仅仅是因为它的接口与专业应用领域所需要的接 口不匹配(名称不一样,参数不一样,等等)。 我们可以改变工具箱类使它兼容专业领域中的类的 接口,但前提是必须有这个工具箱的源代码。然而 即使我们得到了这些源代码,修改工具箱也是没有 什么意义的;因为不应该仅仅为了实现一个应用, 工具箱就不得不采用一些与特定领域相关的接口。
基于对象的Adapter模式的一般结构如下: Adaptee类对象为Adapter所依赖,适配目标 (接口)是Adapter的父类; 基于对象的Adapter模式比较适合应用于 Adapter想为Adaptee添加新的方法的情况。但 在Adaptee类的方法与Adapter类的方法不同名 而实现相同功能的情况下,我们一般也使用基 于对象的Adapter模式,
Adapter模式
效果(类适配器和对象适配器有不同的 权衡)
对象适配器则
允许一个A d a p t e r与多个A d a p t e e—即A d a p t e e 本身以及它的所有子类(如果有子类的话)同时工作。A d a p t e r也可以一次给所有的A d a p t e e添加功能。 使得重定义A d a p t e e的行为比较困难。这就需要生成A d a p t e e的子类并且使得A d a p t e r引用这个子类而不 是引用A d a p t e e本身。
办法之一
New System System
A
B
办法之一
New System
B
办法之二
System
A
B
Adapter
第二种方案的优点
System
Adapter
B
不需要修改代码
新代码
不需要修改代码
办法之三
System
B’
B
下面我们来看一个实际的例子
简化的鸭子接口和类 public interface Duck { public void quack(); public void fly(); }
MallardDuck类简单 地实现了Duck接口。
现在有一种新家伙
public interface Turkey { public void gobble(); public void fly(); }
WildTurkey
public class WildTurkey implements Turkey { public void gobble() { System.out.println("咕咕咕..."); } public void fly() { System.out.println("我在飞,不过飞不远。"); } }
适配器模式详解
目标接口:鸭子接口 目标接口 鸭子接口
被适配者 火鸡接口
适配器 把火鸡装 扮成鸭子 两者无耦合 彼此不必知道对方的存在
客户 要使用鸭子 对象的程序
试ห้องสมุดไป่ตู้看
现在,如果希望把鸭子包装成火鸡该怎 么做? 写出你的代码DuckAdapter
DuckAdapter参考答案
import java.util.Random; public class DuckAdapter implements Turkey { Duck duck; Random rand; public DuckAdapter(Duck duck) { this.duck = duck; rand = new Random(); } public void gobble() { duck.quack(); } public void fly() { if (rand.nextInt(5) == 0) { duck.fly(); } } }
分析以下例子,确定各个类的角色---续
class WebFormDesigner_text_actionAdapter implements java.awt.event.ActionListener { WebFormDesigner adaptee; WebFormDesigner_text_actionAdapter(WebFormDesigner adaptee) { this.adaptee = adaptee; } public void actionPerformed(ActionEvent e) { adaptee.text_actionPerformed(e); } }
鸭子接口Duck,定 义了鸭子具有“鸣 叫”和“飞行”方 法
MallardDuck类
public class MallardDuck implements Duck { public void quack() { System.out.println(" 嘎嘎嘎..."); } public void fly() { System.out.println(" 我在飞哦!"); } }
Adapter模式
参与者
Ta r g e t
C l i e n t使用的与特定领域相关的“接口”。
Client
与符合Ta rg e t接口的对象协同的专业系统。
Adaptee
一个已经存在的“接口”,它具有Client要求的功能但不 符合Client的接口要求。这个接口需要适配。
Adapter
对A d a p t e e的接口与Ta rg e t接口进行适配
Adapter模式
协作
Client在A d a p t e r实例上调用一些操作 (请求)。接着适配器调用A d a p t e e的 操作实现这个请求。
Adapter模式
效果(类适配器和对象适配器有不同的权衡)
类适配器
用一个具体的A d a p t e r类对A d a p t e e和Ta rg e t进 行匹配。结果是当我们想要匹配一个类以及所有它的子类 时,类A d a p t e r将不能胜任工作。 使得A d a p t e r可以重定义A d a p t e e的部分行为,因 为A d a p t e r是A d a p t e e的一个子类。 仅仅引入了一个对象,并不需要额外的指针以间接得到a d a p t e e。
相关主题