简介
为什么要使用适配器模式
通常情况下,客户端可以调用目标类的接口来访问它的服务。但目标类提供的接口不一定是客户端所期望的。这时就需要适配器模式。适配器模式包装目标类即适配者(Adaptee)成适配器。适配器提供客户端所需要的接口,把客户端的请求转化成对适配者的调用。也就是说,客户端访问适配器时,在适配器内部将调用适配者的方法。
什么是适配器模式
适配器模式(Adapter Pattern):将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。
别名
包装器(Wrapper)
类型
结构型模式。既可以作为类结构型模式,也可以作为对象结构型模式。
角色
角色
- Target:目标抽象类
- 可以是一个抽象类或接口,也可以是具体类。
- 目标抽象类的接口被客户端调用。
- 目标抽象类定义客户所需接口。
- Adapter:适配器类
- 作为一个转换器,对Adaptee和Target进行适配。
- 对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
- 类适配器中,它继承继承Target和Adaptee使二者产生联系。
- Adaptee:适配者类
- 包含了客户端需要的方法。但由于某些原因不能直接调用,所以需要被适配。
- Client:客户类
- 客户类。在客户类中针对目标抽象类进行编程,调用在目标抽象类中定义的业务方法。
UML类图
适配器模式有对象适配器和类适配器两种实现。
对象适配器UML类图
在对象适配器模式中,适配器类继承了目标抽象类并定义了一个适配者类的对象实例,在所继承的目标抽象类方法中调用适配者类的相应业务方法。
类适配器UML类图
在类适配器模式中,适配器类实现了目标抽象类接口并继承了适配者类,并在目标抽象类的实现方法中调用所继承的适配者类的方法。
实现
对象适配器
Client.java
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target tar = new Adapter(adaptee);
tar.request();
}
}
Target.java
public abstract class Target {
public abstract void request();
}
Adapter.java
class Adapter extends Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}
Adaptee.java
public class Adaptee {
public void specificRequest(){
System.out.println("This is specificRequest");
}
}
类适配器
Client.java
public class Client {
public static void main(String[] args) {
Target tar = new Adapter();
tar.request();
}
}
Target.java
public interface Target {
public void request();
}
Adapter.java
class Adapter extends Adaptee implements Target {
public void request() {
specificRequest();
}
}
Adaptee.java
public class Adaptee {
public void specificRequest(){
System.out.println("This is specificRequest");
}
}
优缺点
优点
- 耦合性低。将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
- 增加了类的透明性和复用性。将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
- 符合“开闭原则”。可以在不修改原有代码的基础上增加新的适配器类。
对象适配器还具有以下优点
- 一个适配器可以匹配多个适配者。
Adaptee adaptee = new Adaptee();
Target tar = new Adapter(adaptee);
tar.request();
Adaptee2 adaptee2 = new Adaptee2();
Target tar = new Adapter(adaptee2);
tar.request();
类适配器还具有以下优点
- 灵活性更强。因为适配器类是适配者类的子类,所以在适配器类中可以覆盖适配者类中的方法。
类适配器缺点
- 适配器类只能适配一个适配者。
对象适配器缺点
- 灵活性不强。在适配器类中覆盖适配者类中的方法较为困难。
适用场景
- 系统需要使用现有的类,而类的接口不符合系统的需要。
- 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
适用场景
- JDBC。JDBC给出一个客户端通用的抽象接口,每一个具体数据库引擎(如SQL Server、Oracle、MySQL等)的JDBC驱动软件都是一个介于JDBC接口和数据库引擎接口之间的适配器软件。
问题
在软件设计中,你在哪里使用了适配器模式?
待补充。