适配器模式(Adapter Pattern)
概念:
定义:适配器模式 将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
组成:
Client:客户端,直接操控适配器。
Target(目标接口):适配器实现的目标接口。
Adapter:适配器,当被调用时委托给被适配者。
Adaptee:被适配者,适配器所有的请求都委托给自己。
注:上图是对象适配器模式,在支持多重继承的语言中(Java 不支持)我们可以使用 类 适配器模式,将 Adapter 继承 Target 和 Adaptee 即可,继承后 Adapter 可响应两个类的请求。
例子:
鸭子和火鸡都会叫和飞,现有我们需要将火鸡和鸭子伪装起来,用火鸡来冒充鸭子,鸭子和火鸡的叫声不同,并且鸭子飞行距离是火鸡的 5 倍。
Duck 接口类,包含 quack 和 fly 方法
public interface Duck {
public void quack();
public void fly();
}
绿头鸭类
public class MallardDuck implements Duck {
public void quack() {
System.out.println("quack");
}
public void fly() {
System.out.println("I'm flying");
}
}
火鸡类
public interface Turkey {
public void gobble();
public void fly();
}
火鸡具体类
public class WildTurkey implements Turkey {
public void gobble() {
System.out.println("Gobble gobble");
}
public void fly() {
System.out.println("I'm fly a short distance");
}
}
适配器类
public class TurkeyAdatptor implements Duck {
Turkey turkey;
public TurkeyAdatptor(Turkey turkey) {
this.turkey = turkey;
}
public void quack() {
turkey.gobble();
}
public void fly() {
for (int i = 0; i < 5; i++) {
turkey.fly();
}
}
}
测试代码:
public class DuckTestDrive {
public static void main(String[] args) {
MallardDuck duck = new MallardDuck();
WildTurkey turkey = new WildTurkey();
Duck turkeyAdapter = new TurkeyAdatptor(turkey);
System.out.println("The Turkey says...");
turkey.gobble();
turkey.fly();
System.out.println("\nThe Duck says...");
duck.quack();
duck.fly();
System.out.println("\nThe Adatper Duck says");
turkeyAdapter.quack();
turkeyAdapter.fly();
}
}
运行结果:
适用场景:
- 你想使用一个已经存在的类,而它的 接口 不符合你的需求。
- 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
- (仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。即仅仅引入一个对象,并不需要额外的指针以间接取得adaptee。
优缺点:
优点:
- 适配器模式也是一种包装模式,它与装饰模式同样具有包装的功能,此外,对象适配器模式还具有委托的意思。总的来说,适配器模式属于补偿模式,专用来在系统后期扩展、修改时使用。
缺点:
- 过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
完
参考:
《Head first 设计模式》