1、什么是适配器模式
适配器(Adapter)模式又叫做包装( Wrapper )模式,是由GOF提出的23种设计模式中的一种结构型设计模式,Adapter模式的设计意图:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
2、适配器模式的结构
适配器模式分为类适配器模式(采用继承方式实现)、对象适配器模式(采用对象组合方式实现)和接口适配器模式三种。
类适配器通过继承对一个类与另一个接口进行匹配,如下图所示。
类适配器模式涉及的角色及其职责如下:
客户端(Client)类:该类需要与符合条件的特定的接口协同工作。
目标(Target)接口类:客户端所需要的接口,在类适配器模式下该角色只能是接口。
适配者(Adaptee)类:需要被适配的类,适配者类一般是一个具体类,包含了客户端希望使用的某些业务方法。
适配器(Adapter)类:该类对适配者类和目标接口进行适配,在类适配器模式下通过继承方式实现,即:Adapter 继承 Adaptee 并实现Target接口。
类适配器模式结构示意源代码如下:
Target目标接口类是Client客户端类所需要的与特定领域相关的接口。
public interface Target {
// Adaptee适配者有此方法的实现,但方法名可以不同
void specificOperation();
// Adaptee适配者没有的其他方法
void otherOperation();
}
// Adaptee适配者类包含了客户端希望使用的某些业务方法,但Adaptee类不符合Client类所需的接口要求
public class Adaptee {
public void operation() {
System.out.println("执行Adaptee的operation()方法...");
}
}
Adapter适配器类继承Adaptee适配者类并实现Target接口,这样 Adapter 既符合 Client 所需接口的要求,又可以继承原属于 Adaptee 的方法。
public class Adapter extends Adaptee implements Target {
@Override
public void specificOperation() {
this.operation();
}
@Override
public void otherOperation() {
System.out.println("执行Adapter的otherOperation()方法...");
}
}
为简单起见我们为 Client 添加一个 clientOperation()方法,该方法需要传入一个Target接口对象,在该Target接口对象中我们要复用现有的 Adaptee 的方法
public class Client {
public static void clientOperation(Target target) {
target.specificOperation();
target.otherOperation();
}
public static void main(String[] args) {
Adapter adapter = new Adapter();
clientOperation(adapter);
}
}
运行程序打印结果如下:
执行Adaptee的operation()方法...
执行Adapter的otherOperation()方法...
对象适配器通过组合对一个类及其子类与另一个接口进行匹配。
对象适配器模式涉及的角色及其职责如下:
客户端(Client)类:该类需要与符合条件的特定的接口协同工作。
目标(Target)接口类:客户端所需要的接口,在对象适配器模式下该角色可以是接口、抽象类或者非final的具体类。
适配者(Adaptee)类:需要被适配的类,适配者类一般是一个具体类,包含了客户端希望使用的某些业务方法。
适配器(Adapter)类:该类对适配者类和目标接口进行适配,在对象适配器模式下通过组合方式实现,即:Adapter 类继承 Target 类或者实现 Target 接口,并在其内部包含一个 Adaptee 对象的引用,通过对其内部的 Adaptee 引用的方法调用实现客户端所需要的接口。
接下来以 Target 为接口的情况举例,对象适配器模式结构示意源代码如下:
Target 是 Client 所需要的与特定领域相关的接口。
public interface Target {
// Adaptee适配者有此方法的实现,但方法名可以不同
void specificOperation();
// Adaptee适配者没有的其他方法
void otherOperation();
}
Adaptee 包含了 Client 希望使用的某些业务方法,但 Adaptee 不符合 Client 的接口要求。
public class Adaptee {
public void operation() {
System.out.println("执行Adaptee的operation()方法...");
}
}
Adapter 实现 Target 接口,并在其内部包含一个 Adaptee 对象的引用,通过对其内部的 Adaptee 对象的方法调用来实现客户端所需要的接口。
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
super();
this.adaptee = adaptee;
}
@Override
public void specificOperation() {
this.adaptee.operation();
}
@Override
public void otherOperation() {
System.out.println("执行Adapter的otherOperation()方法...");
}
}
同样的,Client 依旧要与一个 Target 接口协同工作,对Client进行简单修改。
public class Client {
public static void clientOperation(Target target){
target.specificOperation();
target.otherOperation();
}
public static void main(String[] args) {
Adapter adapter = new Adapter(new Adaptee());
clientOperation(adapter);
}
}
运行程序打印结果如下:
执行Adaptee的operation()方法...
执行Adapter的otherOperation()方法...
接口适配器模式又被叫作缺省适配器(DefaultAdapter)模式,DefaultAdapter 为一个接口提供缺省实现,这样需实现该接口的类就可以直接从 DefaultAdapter 进行扩展,而不必再从原有接口进行扩展。当原接口中定义的方法很多,而其中大部分方法又不被需要时,这种模式非常实用。由缺省适配器类(由于该类一般都只为接口提供缺省的空实现,所以该类一般都被定义为抽象类)直接实现接口,并为所有方法提供缺省实现。这样,如果有用户类需要实现该接口就可以直接继承适配器类,并只需实现感兴趣的方法就可以了。
缺省适配器模式涉及的角色及其职责如下:
目标(Target)接口类:用户类所需要实现的接口,定义有很多方法,但这些方法不一定全都被用户类所需要。
缺省适配器(DefaultAdapter)类:实现目标接口,并为所有接口方法提供缺省实现。
具体(ConcreteClass)用户类:用户类要实现目标接口,但是又用不到接口所规定的所有的方法。
类适配器模式结构示意源代码如下:
Target接口类是用户类所需要实现的接口,该接口定义有很多方法。
目标(Target)接口类
public interface 和尚 {
public void 吃斋();
public void 念经();
public void 打坐();
public void 撞钟();
public void 习武();
public String getName();
}
// 缺省适配器(DefaultAdapter)类
public abstract class 天星 implements 和尚 {
public void 吃斋(){}
public void 念经(){}
public void 打坐(){}
public void 撞钟(){}
public void 习武(){}
public String getName(){
return null;
}
}
// 具体(ConcreteClass)用户类
public class 鲁智深 extends 天星{
public void 习武(){
拳打镇关西;
大闹五台山;
大闹桃花村;
火烧瓦官寺;
倒拔垂杨柳;
}
public String getName(){
return "鲁智深";
}
}
三、适配器模式的选择
通过使用适配器模式,我们可以达到以下目的:
5.1 复用现有的类,解决现有类和复用环境要求不一致的问题。
5.2 将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
5.3 一个对象适配器可以把适配者类和它的子类都适配到目标接口。
类适配器模式和对象适配器模式比较:
-类适配器通过继承方式来实现,是静态的;而对象适配器通过组合方式来实现,是动态的。
-对于类适配器,适配器直接继承自 Adaptee ,这使得适配器不能和 Adaptee 的子类一起工作。
-对于对象适配器,同一个适配器可以把 Adaptee 和它的子类都适配到目标接口。
-对于类适配器,适配器可以重定义 Adaptee 的部分行为,相当于子类覆盖父类的部分实现方法。
-对于对象适配器,要重定义 Adaptee 的行为比较困难,这种情况下,需要定义 Adaptee 的子类来实现重定义,然后让适配器组合子类。
原文:https://blog.csdn.net/pengjunlee/article/details/52347644