关于适配器,我们生活中常见的许多东西都可以称之为适配器,比如Mac电源适配器(可是我没有!!),还有漏斗等,在设计模式中的意义是相同的。所谓适配器模式就是将一个类的接口转换成满足新需求的另一个接口,适配器让原本接口不兼容的类可以进行合作。
我们就以Mac电源适配器为例:
【需求场景】
Mac笔记本没电了,需要充电,但是它对应的充电接口只能是Apple自己设计的,但是现实是目前只有公共的充电接口,所以,没有办法只能把这两个接口通过一个中间件连接起来,那么问题来了这个中间件怎么设计才能满足需求?
【问题剖析】
首先明确职责,实际完成充电工作是通过公共的充电接口,也就是实际干活的不是通过Apple自己设计的接口,Apple自己设计的接口负责的是与Mac笔记本中充电部件的交互,那么中间件干的事就是替代Apple自带的接口与充电组件交互,但是实际工作又得让公共接口负责。
【问题解决】
定义三个类,分别为ApplePort
,NormalPort
以及NormalPortAdapter
,如下:
public interface ApplePort{
public void appleCharge();
}
public interface NormalPort{
public void normalCharge();
}
public class NormalPortAdapter implements ApplePort {
// 定义由NormalPort做实际的工作
private NormalPort normalPort;
public NormalPort(NormalPort normalPort){
this.normalPort = normalPort;
}
@Override
public void appleCharge(){
normalPort.normalPort();
}
}
ApplePort applePort = new NormalPortAdapter(new NormalPort(){
@Override
public void normalCharge(){
// 实际工作的类,此处声明为匿名类
};
});
applePort.appleCharge();
从上面中整个问题的解决过程中可以发现:
- Mac充电时只知道电是从自己定义的接口中来的,并不知道实际上电是由
NormalPort
提供的,说明客户和被是配者是解耦的; - 适配器,也就是这里说的“中间件”,实现了目标接口,但是保存有被适配者的引用,它起到的实际上是一个翻译的作用;
- 被适配的接口,这里指
NormalPort
接口,在本例中使用的是一个匿名类,实际上可以根据多态随意的使用实现类,比如充电时的200V或者220V都可以;
【问题深入】
但是从上面还有一个问题,如果我有两个电脑,一个是Mac,一个是普通的PC,普通PC充电时需要的就是通用的接口,那么适配器如何满足这种需求?能不能也让我们的适配器实现被适配的接口,如下:
public class NormalPortAdapter implements ApplePort, NormalPort {
// 定义由NormalPort做实际的工作
private NormalPort normalPort;
public NormalPort(NormalPort normalPort){
this.normalPort = normalPort;
}
@Override
public void appleCharge(){
normalPort.normalPort();
}
@Override
public void normalCharge(){
// do something
}
}
使用上面这种方法可以用一个适配器同时满足两种需求,而且在实现的过程中最好将对应ApplePort
的NormalPort
功能和适配器自己实现的NormalPort
解耦,这样针对两种不同的需求,在底层的实现也是不同的。
该设计模式的UML类图如下:
相关文章: