什么是适配器模式
适配器模式,它能使接口不兼容的对象能够相互合作,协同工作。
例如:现实中,出国旅游,国内时电压220V,手机充电器正常使用,但到日本电压为110V左右,不能直接使用。这时就需要一个适配器(电压转换装置),将110V转化为220V。适配器模式就是类似这样的作用。
注:适配器模式是一种结构型模式(这类模式介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效)。
主要角色
适配器模式(Adapter)包含以下3个主要角色。
目标(Target)接口:客户期待的接口,它可以是抽象类或接口。
适配者(Adaptee)类:被访问而需要适配的组件接口。
适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
分类
适配器模式主要有两类:对象适配器模式和类适配器模式。
对象适配器模式
对象适配器实现了其中一个对象的接口, 并对另一个对象进行封装。
对象适配器模式可釆用将现有组件库中已经实现的组件(Adaptee)引入适配器类中,该类同时实现当前系统的业务接口(Target)。
大致代码如下(便于理解):
//目标接口
public interface Target {
public void request();
}
//适配者接口
public class Adaptee {
public void specificRequest() {
System.out.println("适配者中的业务代码被调用!");
}
}
//对象适配器类
public class ObjectAdapter implements Target {
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee) {
this.adaptee=adaptee;
}
public void request() {
adaptee.specificRequest();
}
}
//客户端代码
public class ObjectAdapterTest {
public static void main(String[] args) {
System.out.println("对象适配器模式测试:");
Adaptee adaptee = new Adaptee();
Target target = new ObjectAdapter(adaptee);
target.request();
}
}
//输出结果:
对象适配器模式测试:
适配者中的业务代码被调用!
类适配器模式
适配器同时继承两个对象的接口。
请注意,这种方式仅能在支持多重继承的编程语言中实现。
例如 C++可定义一个适配器类来同时继承当前系统的业务接口(Target)和现有组件库中已经存在的组件接口(Adaptee)。Java不支持多继承,但变通一下,可以定义一个适配器类来实现当前系统的业务接口(Target),同时又继承现有组件库中已经存在的组件(Adaptee)。
看下面代码,便于理解
类适配器C++ 多继承方式
#include
using namespace std;
// "Target"
class Target {
public:
virtual void Request(){};
};
// "Adaptee"
class Adaptee {
public:
void SpecificRequest() {
cout<<"Called SpecificRequest()"<SpecificRequest();
}
};
int main() {
Target *t = new Adapter();
t->Request();
return 0;
}
Java 变通方式
//目标接口
public interface Target {
public void request();
}
//适配者接口
public class Adaptee {
public void specificRequest() {
System.out.println("适配者中的业务代码被调用!");
}
}
//类适配器类
public class ClassAdapter extends Adaptee implements Target {
public void request() {
specificRequest();
}
}
//客户端代码
public class ClassAdapterTest {
public static void main(String[] args) {
System.out.println("类适配器模式测试:");
Target target = new ClassAdapter();
target.request();
}
}
//输出结果:
类适配器模式测试:
适配者中的业务代码被调用!
相对的,一般多使用对象适配器。
除了类似java不支持多重继承外。类适配器直接继承了适配者类,导致类之间耦合高,需了解其内部结构才可以。同时,对于类适配器,更换适配器也相对复杂。
优缺点
优点:
目标类和适配者类解耦,增加了类的透明性和复用性,同时系统的灵活性和扩展性都非常好,更换适配器或者增加新的适配器都非常方便,符合“开闭原则”。
缺点:
过多地使用适配器,会让系统非常零乱,不易整体进行把握。
比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
实例 demo
给手机充电需要充电器(线路输出电压220V,给手机充电输出电压5V)。这里目标接口是输出5v,适配者是线路输出电压220V,通过适配器达到要求。
//目标接口
public interface TargetVoltage {
void output5V();
}
//适配者:线路输出电压220V
public class AdapteeVoltage {
private int output = 220;
public int output220V() {
System.out.println("电源输出电压:"+output+"V");
return output;
}
}
//对象适配器
public class VoltageAdapter implements TargetVoltage {
private AdapteeVoltage adapteeV;
public VoltageAdapter(AdapteeVoltage adapteeV) {
this.adapteeV=adapteeV;
}
public void output5V() {
int output = adapteeV.output220V();
System.out.println("电压适配器工作开始");
output = output/44;
System.out.println("经过电源适配器转换后电压:"+output+"V");
}
}
//客户端调用
public class AdapterTest {
public static void main(String[] args) {
AdapteeVoltage adapteeVoltage = new AdapteeVoltage();
TargetVoltage target = new VoltageAdapter(adapteeVoltage);
target.output5V();
}
}
//输出结果
电源输出电压:220V
电压适配器工作开始
经过电源适配器转换后电压:5V