适配器模式

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Adaptee adaptee=new Adaptee(); public void Request() {
adaptee.SpecificRequest(); } }
public class Client {
public static void main(String[] args) {
ITarget t = new Adapter(); t.Request(); } }
对象适配器效果 ① 允许一个Adapter与多个Adaptee及它们所
有子类同时工作。Adapter也可以一次给 所有的Adaptee添加功能 ② 使得重定义Adaptee的行为比较困难。这 就 需 要 生 成 Adaptee 的 子 类 并 且 使 得 Adapter引用这个子类而不是引用Adaptee 本身。
} }
类适配器效果
① 用Adapter类对Adaptee和Target进行匹配。 当想要匹配一个类以及所有它的子类时, 类Adapter将不能胜任工作
② 使得Adapter可以重定义Adaptee的部分行 为,因为Adapter是Adaptee的一个子类。
③ 仅仅引入一个对象,并不需要额外的指针 以间接得到adaptee
this.turkey = turkey;
} public void quack() {
火鸡适配器包装了一 个火鸡对象,同时实
turkey.gobble(); } public void fly() {
现了鸭子接口。这样 就可以像使用鸭子一 样使用火鸡了。
for(int i=0; i < 5; i++) {
duck.fly();
}
}
需要使用鸭子对象
分析
目标接口:鸭子接口
被适配者 火鸡接口
适配器
把火鸡装 扮成鸭子
客户
要使用鸭子 对象的程序
两者无耦合 彼此不必知道对方的存在
试试看
➢如果希望把鸭子包装成火鸡该怎么做? ➢写出你的代码DuckAdapter
DuckAdapter
import java.util.Random; public class DuckAdapter implements Turkey {
duck.fly(); } } }
概念理解
适配器模式 把一个类的接口(被适配者)变换成客户端所期待的另一种 接口(目标),从而使原本因接口原因不匹配而无法一起 工作的两个类能够一起工作。 该模式中涉及有目标、被适配者和适配器。
➢ 适配器模式的关键是建立一个适配器,这个适 配器实现了目标接口并包含有被适配者的引用。
➢ Adapter包装一个Adaptee的实例,从而将客 户端与Adaptee衔接起来
➢ 由于Adapter与Adaptee是委派关系,这决定 了这个适配器模式是对象的
//目标 public interface ITarget { // Methods
void Request(); }
//被适配者 public class Adaptee {
// 适配器 public class Adapter extends Adaptee implements ITarget {
public void Request() { this.SpecificRequest();
} }
public class Test {
public static void main(String[] args) { ITarget t=new Adapter(); t.Request();
➢ 别名:包装器(Wrapper),变压器模式
适配器模式的结构与使用
适配器模式的两种形式: ①类的适配器模式 ②对象的适配器模式
类的适配器模式(Class Adapter)结构
Client
Target
+ request () ...
Adaptee
+ specificRequest () ...
Adapter + request ()
}
问题?
➢我们原来有一个程序使用鸭子对象,现在 想让它使用火鸡对象,但是火鸡与鸭子的 接口不同,不能直接使用。
写一个火鸡适配器,让火鸡看起来像鸭子
火鸡适配器
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
适配器模式(Adapter)
2020/4/12 1
结构型模式
结构型模式(Structural Pattern)描述如何将 类或者对象结合在一起形成更大的结构, 就像搭积木,可以通过简单积木的组合形 成复杂的、功能更为强大的结构。
结构型模式
➢ 结构型模式分为类结构型模式和对象结构型模式: ✓类结构型模式关心类的组合,由多个类可以 组合成一个更大的系统,在类结构型模式中 一般只存在继承关系和实现关系。 ✓对象结构型模式关心类与对象的组合,通过 关联关系使得在一个类中定义另一个类的实 例对象,然后通过该对象调用其方法。
public void SpecificRequest() // Methods {
System.out.println("Called SpecificRequest()" ); } }
// 适配器 public class Adapter extends Adaptee implements ITarget {
Adapter(适配器)模式
➢“不合适的插座”
✓你的电脑的插头是三相的 ✓而墙上的插座只有两相的 ✓插头和插座的“接口”不匹配,怎么办?
Adapter(适配器)模式 ➢接口转换
客户
请求
转换后的请求
适配器
面向对象软件系统的适配问题
假设我们已经有一个软件系统,原来使用 了一个第三方类库A。现在有一个新的第三 方类库B,其功能等各方面都更加强大。 我们希望用B来替换A,以改善我们的系统。 但是B的接口与A不一样。那怎么办呢?
}
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("我在飞,不过飞不远"); }
Duck turkeyAdapter = new TurkeyAdapter(turkey);
System.out.println("火鸡说...");
turkey.gobble();
在需要鸭子对象的
turkey.fly();
地方使用了火鸡适
System.out.println("\n鸭子说...");
➢ 被适配者Adaptee类没有Request方法,而客 户期待这个方法
➢ 为使客户能够使用Adaptee类,提供一个中 间环节,即类Adapter类
➢ Adapter类实现Target接口,继承Adaptee, Adapter 的 Request 方 法 重 新 封 装 Adaptee 的 SpecificRequest方法,实现适配的目的
配器对象, 火鸡适
testDuck(duck);
配器对象包装了一
System.out.println("\n火鸡适配器说...");
个火鸡对象,所以
testDuck(turkeyAdapter);
实际使用的是火鸡
}
对象。
static void testDuck (Duck duck) {
duck.quack();
结构型模式
根据“合成复用原则”,在系统中尽量 使用组合关系来替代继承关系,因此大 部分结构型模式都是对象结构型模式。
结构型模式
➢结构型模式简介 – 适配器模式(Adapter) – 桥接模式(Bridge) – 组合模式(Composite) – 装饰模式(Decorator) – 外观模式(Facade) – 享元模式(Flyweight) – 代理模式(Proxy)
适配器模式的优缺点
➢ 对象适配器模式优点: 一个对象适配器可以把多个不同的适配者适配到同一个目标, 也就是说,同一个适配器可以把适配者类和它的子类都适 配到目标接口。
➢ 对象适配器模式缺点: 与类适配器模式相比,要想置换适配者类的方法就不容易。 如果一定要置换掉适配者类的一个或多个方法,就只好先 做一个适配者类的子类,将适配者类的方法置换掉,然后 再把适配者类的子类当做真正的适配者进行适配,实现过 程较为复杂。
办法之一
New System
B
办法之二
System
A
B
Adapter
第二种方案的优点
System
Adapter
B
不需要修改代码
新代码
不需要修改代码
办法之三
System
B’
B
示例
➢鸭子接口 public interface Duck {
public void quack(); public void fly(); }
turkey.fly();
}
}
}
使用适配器
public class DuckTestDrive {
public static void main(String[] args) {
MallardDuck duck = new MallardDuck();
WildTurkey turkey = new WildTurkey();
适配器模式的优缺点
➢将目标类和适配者类解耦,通过引入一个适配器类 来重用现有的适配者类,而无须修改原有代码。
➢增加了类的透明性和复用性,将具体的实现封装在 适配者类中,对于客户端类来说是透明的,而且提 高了适配者的复用性。
➢灵活性和扩展性都非常好,通过使用配置文件,可 以很方便地更换适配器,也可以在不修改原有代码 的基础上增加新的适配器类,完全符合“开闭原 则”。
适配器模式的优缺点
➢类适配器模式优点: 由于适配器类是适配者类的子类,因此可以在适 配器类中置换一些适配者的方法,使得适配器的 灵活性更强。
➢类适配器模式缺点: 对于不支持多重继承的语言,一次最多只能适配 一个适配者类,而且目标抽象类只能为抽象类, 不能为具体类,其使用有一定的局限性,不能将 一个适配者类和它的子类都适配到目标接口。
对象适配器模式(Object Adapter)结构
Client
Target
+ request () ...
Adaptee
+ specificRequest () ...
Adapter adaptee + request ()
...
adaptee.specificRequest();
➢ 客户端需要调用Request方法,而Adaptee没 有该方法,为了使客户端能够使用Adaptee 类,需要提供类Adapter
//目标 public interface ITarget {
void Request(); }
//被适配者 public class Adaptee {
public void SpecificRequest() {
System.out.println("called SpecificRequest()"); } }
鸭子接口Duck,定义 鸭子具有“鸣叫”和
“飞行”方法
MallardDuck类
public class MallardDuck implements Duck { public void quack() { System.out.println("嘎嘎嘎..."); } public void fly() { System.out.println("我在飞哦!"); }
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) {
...
spቤተ መጻሕፍቲ ባይዱcificRequest();
➢客户Client ➢目标(Target) 客户所期待的接口 ➢被适配者(Adaptee):一个已经存在的、需
要适配的类,它具有Client要求的功能但不符 合Client的接口要求 ➢适配器(Adapter) ✓对Adaptee的接口与Target接口进行适配 ✓适配器模式的核心类
相关文档
最新文档