目录
在很久很久以前,耳机几乎都是3.5mm的接口,大部分电子设备耳机的插孔也都是3.5mm。大家一直都遵循这个规则。突然有一天,苹果跳出来说,我的手机不要3.5mm的耳机接口了,充电接口就是耳机接口。我们的耳机也会做成相应的插孔。
这下大家就傻了。我耳机都是3.5mm的接口,你苹果产品不能用这些耳机了,这不是玩呢吗?苹果这一举措导致了Iphone7以后的产品都无法正常使用3.5mm接口了。
耳机大厂就开骂了,我不可能为了你苹果就修改我的耳机接口啊。所以这时候就出现了一个东西,转换器。
苹果耳机转换器能将3.5mm的耳机用在苹果设备上,达到了一个适配的功能。
一、定义
适配器模式:将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。
文章开头的例子,就是一个典型的适配器模式。他对原本不兼容的3.5mm耳机和苹果设备做了适配,使他们可以正常使用。
二、结构
适配器模式有三个角色:
-
Target(目标抽象类):这个接口定义了客户所需要的功能。在前面的例子中,target就是转换器。
-
Adapter(适配器):这是target的具体实现类,定义了具体怎么适配。在前面的例子中,adapter是苹果耳机转换器。
-
Adaptee(适配者):这是Adapter要适配的东西。在前面的例子中,Adaptee是耳机。
三、代码实现
1、耳机适配器例子
首先我们来写一个耳机类。耳机的作用就是播放声音。
public class Earphone {
public void playSound() {
System.out.println("耳机播放声音");
}
}
然后定义一个耳机适配器的接口,作用就是适配各种耳机
public interface EarPhoneAdapter {
void adaption();
}
然后,就是一个具体的适配器。将普通耳机适配到IOS设备。
public class ToIosAdapter extends Earphone implements EarPhoneAdapter{
@Override
public void adaption() {
System.out.println("使用转换器适配到苹果手机");
super.playSound();
}
}
注意这里,我们通过继承Earphone来达到适配的效果。这种继承方式的适配器叫做类适配器。
但是,由于Java单继承的特性,类适配器就只能适配一个类,有一定的局限性。后面我们会再说到通过组合方式的对象适配器。
这时候我们就可以正常使用转换器了
public class Client {
public static void main(String[] args) {
EarPhoneAdapter adapter = new ToIosAdapter();
adapter.adaption();
}
}
运行结果:
然后众所周知,后来华为也取消了3.5mm耳机孔,也和充电孔共用了。这时候我们要添加Type-C的适配器,也无需修改原本的代码,新增一个新的适配器就好,符合开闭原则。
2、耳机充电器适配器例子
虽然耳机适配器已经能满足大部分用户的需求。但是还是有用户不满,我以前能同时用耳机听歌和充电,现在你就一个孔,让我怎么同时做两件事。没关系,我们就出一个能满足两个需求的适配器。
我们新添加一个充电器类
public class Charger {
public void charge() {
System.out.println("开始充电");
}
}
这时候,用户的对适配器的要求就是既能插耳机听歌,又能充电。所以我们来一个强大的适配器接口。
public interface StrongAdapter {
void playSoundWithEarphone();
void charge();
}
最后实现一个转TypeC的适配器
public class ToTypeCAdapter implements StrongAdapter{
private Earphone earphone;
private Charger charger;
public ToTypeCAdapter(Earphone earphone, Charger charger) {
this.earphone = earphone;
this.charger = charger;
}
@Override
public void playSoundWithEarphone() {
earphone.playSound();
}
@Override
public void charge() {
charger.charge();
}
}
这里我们不再使用继承,而是使用了组合的方式,这种适配器叫对象适配器。
对象适配器的好处在于,可以适配多个类,更加灵活。
然后用户就可以又充电又听歌了。
public class Client {
public static void main(String[] args) {
Earphone earphone = new Earphone();
Charger charger = new Charger();
StrongAdapter adapter = new ToTypeCAdapter(earphone, charger);
adapter.playSoundWithEarphone();
adapter.charge();
}
}
运行结果:
四、特点
-
使用适配器模式可以提高类的复用性,比如耳机厂商不必去生产IOS接口和Type-C插孔的耳机。并且需要新的具体适配器时,无需修改原本的代码,只用新增,符合开闭原则。
1、类适配器和对象适配器的对比
因为Java单继承的特性,类适配器仅能适配一个类。并且抽象适配器只能是一个接口。
而对象适配器采用组合的方式,能够灵活的适配多个类。并且因为没有使用继承,此时的抽象适配器可以是接口,也可以是一个抽象类,可以实现一些公共的方法。并且根据“里氏替换原则”, 适配器还可以适配适配者的子类。
五、适用环境
在系统需要使用一些现有的类,而这些类不符合系统要求,需要适配转换的时候可以使用适配器模式。