一、简介
适配器模式(Adapter Pattern) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式
使用场景
通常情况下,客户端可以通过目标类的接口访问它所提供的服务。有时,现有的类可以满足客户类的功能需要,但是它所提供的接口不一定是客户类所期望的,这可能是因为现有类中方法名与目标类中定义的方法名不一致等原因所导致的
二、三种模式
1.默认适配器模式
public interface Operation {
void init();
void create();
void query();
void update();
void delete();
}
这个接口定义了很多方法,但是我们只需要init和delete方法,我们如果直接实现该接口,就必须实现其它不需要的方法,这时可以加一个适配器类:
public class DefaultAdapter implements Operation {
@Override
public void init() {
System.out.println("初始化!!!");
}
@Override
public void create() {
}
@Override
public void query() {
}
@Override
public void update() {
}
@Override
public void delete() {
System.out.println("删除!!!");
}
}
//继承适配器类
public class SpecialOperation extends DefaultAdapter {
@Override
public void init() {
System.out.println("初始化1000条数据!!!");
}
@Override
public void delete() {
System.out.println("删除100条数据!!!");
}
}
public class Client {
public static void main(String[] args) {
Operation op = new SpecialOperation();
op.init();
op.delete();
}
}
2.对象适配器模式

- Target:目标抽象类
- Adapter:适配器类
- Adaptee:适配者类(适配器类需要持有该类对象)
- Client:客户类
//Target
public interface TwoSocket {
void chargeWithTwoSocket();
}
//Adaptee
public class ThreeSocket {
public void chargeWithThreeSocket() {
System.out.println("使用三项插座");
}
}
// Adapter
public class SocketAdapter implements TwoSocket {
private ThreeSocket threeSocket;
public SocketAdapter(ThreeSocket threeSocket) {
this.threeSocket = threeSocket;
}
@Override
public void chargeWithTwoSocket() {
threeSocket.chargeWithThreeSocket();
}
}
//Client
public class Client {
public static void main(String[] args) {
ThreeSocket threeSocket = new ThreeSocket();
TwoSocket twoSocket = new SocketAdapter(threeSocket);
twoSocket.chargeWithTwoSocket();
}
}
只提供两孔插座,将其适配成三孔插座
SocketAdapter实现target类接口,在实现具体充电方法chargeWithTwoSocket()中,使用自身持有的对象ThreeSocket,调用三孔插座充电方法chargeWithThreeSocket()
3.类适配器模式
public interface Target {
void method1();
void method2();
void method3();
}
public class Concrete {
public void method1() {
System.out.println("方法一执行");
}
public void method2() {
System.out.println("方法二执行");
}
}
public class TargetAdapter extends Concrete implements Target {
@Override
public void method3() {
System.out.println("方法三执行");
}
}
适配器类TargetAdapter实现Target接口,同时持有一个Concrete 类,该类有部分和Target接口相同方法,所以在TargetAdapter中,可以重写Target部分方法,通过继承也自动获取大部分同名方法的实现
三、优缺点
优点:
- 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
- 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
- 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
- 由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强
- 一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点:
类适配器模式的缺点如下:
- 对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
对象适配器模式的缺点如下:
- 与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。