定义:将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
类型:类对象结构型模式
类图:
在GoF的设计模式中,对适配器模式讲了两种类型,类适配器模式和对象适配器模式。由于类适配器模式通过多重继承对一个接口与另一个接口进行匹配,而C#、java等语言都不支持多重继承,因而这里只是介绍对象适配器。
类适配器模式使用多重继承对一个接口和另一个接口进行匹配,如下图所示:
对象适配器模式依赖于对象组合,如下图所示:
在现实生活中,像这种适配器我们经常见到,而且还是经常使用它,如:手机(深信大家都见过),我们手机在充电的时候,不可能直接在220V电源上直接充电,而是手机“充电器”进行转换成手机需要的电压才可以正常充电,否则就不可以完成充电,这个“充电器”就起到了适配的作用。
适配器模式的结构
- 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
- 需要适配的类(Adaptee):需要适配的类或适配者类。
- 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
- 客户端(Client):与符合Target接口的对象协同。
代码实现
1、类适配器模式的代码实现
//Target
interface Target {
public void request();
}
//Adaptee
class Adaptee {
public void specificRequest() {
System.out.println("specificRequest...");
}
}
// Adapter
//直接继承自Adaptee 采用继承实现
class Adapter extends Adaptee implements Target {
@Override
public void request() {
this.specificRequest();
}
}
//Client
public class AdapterClient {
/**
* @param args
*/
public static void main(String[] args) {
Target target = new Adapter();
target.request();
}
}
2、对象适配器模式的代码实现
//Target
interface Target {
public void request();
}
//Adaptee
class Adaptee {
public void specificRequest() {
System.out.println("specificRequest...");
}
}
//Adapter
//实现 Target接口 采用对象组合方式实现
class Adapter implements Target {
private Adaptee mAdaptee;
public Adapter(Adaptee mAdaptee) {
this.mAdaptee = mAdaptee;
}
@Override
public void request() {
mAdaptee.specificRequest();
}
}
public class AdapterClient2 {
/**
* @param args
*/
public static void main(String[] args) {
Adaptee mAdaptee = new Adaptee();
Target target = new Adapter(mAdaptee);
target.request();
}
}
适配器模式的优缺点
优点
- 通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。
- 复用了现存的类,解决了现存类和复用环境要求不一致的问题。
- 将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
- 一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
对于对象适配器来说,更换适配器的实现过程比较复杂。
适用场景
- 系统需要使用现有的类,而这些类的接口不符合系统的接口。
- 想要建立一个可以重用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
- 两个类所做的事情相同或相似,但是具有不同接口的时候。
- 旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,但我们不希望手动更改原有类的时候。
- 使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。
总结
总之,通过运用Adapter模式,就可以充分享受进行类库迁移、类库重用所带来的乐趣,以达到更好的复用。