一、是什么?
定义: 将一个类的接口变成另外一个类所期待的另一个接口, 从而使因接口不匹配而无法一起工作的两个类能够一起工作
举个例子, 苹果手机想用type-c的充电器充电, 但充电接口不吻合, 所以就选哦一个转接头, 使type-c
能给苹果手机充电, 这就是适配器
二、适配器的三种实现
2.1 接口适配器模式
SpringMvc中因为handler有三种实现方式(implements Controller、implements HttpRequestHandler、@RequestMapping),要执行这三种handler的话,需要对应适配器才行。这就是接口适配器模式的实际应用之一。
下面的例子用type-c充任何电器
2.1.1类图
2.1.2 代码实现
注:support方法判断当前适配器是否适配这个数码电器
// 被适配的数码电器接口
public interface DigitalAppliance {
void charge();
}
// 耳机
public class Earphone implements DigitalAppliance{
@Override
public void charge() { System.out.println("earphone charge...");}
}
// 手机
public class Phone implements DigitalAppliance{
@Override
public void charge() { System.out.println("phone charge...");}
}
// Mp3
public class Mp3 implements DigitalAppliance{
@Override
public void charge() { System.out.println("mp3 charge...");}
}
// 期望的接口
public interface ChargeAdapter {
void charge(DigitalAppliance digitalAppliance);
boolean support(DigitalAppliance digitalAppliance);
}
// 耳机充电适配器
public class EarphoneChargeAdapter implements ChargeAdapter{
@Override
public void charge(DigitalAppliance digitalAppliance) {
System.out.println("转为Earphone充电...");
digitalAppliance.charge();
}
@Override
public boolean support(DigitalAppliance digitalAppliance) {
return digitalAppliance instanceof Earphone;
}
}
// 手机充电适配器
public class PhoneChargeAdapter implements ChargeAdapter{
@Override
public void charge(DigitalAppliance digitalAppliance) {
System.out.println("转为phone充电...");
digitalAppliance.charge();
}
@Override
public boolean support(DigitalAppliance digitalAppliance) {
return digitalAppliance instanceof Phone;
}
}
// Mp3充电适配器
public class Mp3ChargeAdapter implements ChargeAdapter{
@Override
public void charge(DigitalAppliance digitalAppliance) {
System.out.println("转为mp3充电...");
digitalAppliance.charge();
}
@Override
public boolean support(DigitalAppliance digitalAppliance) {
return digitalAppliance instanceof Mp3;
}
}
public class Typec {
private static final List<ChargeAdapter> CHARGE_ADAPTERS = new ArrayList<>();
static {
// 获取所有的适配器
CHARGE_ADAPTERS.add(new PhoneChargeAdapter());
CHARGE_ADAPTERS.add(new EarphoneChargeAdapter());
CHARGE_ADAPTERS.add(new Mp3ChargeAdapter());
}
public static void main(String[] args) {
DigitalAppliance digitalAppliance = new Phone();
// 获取合适的适配器
ChargeAdapter chargeAdapter = getChargeAdapter(digitalAppliance);
chargeAdapter.charge(digitalAppliance);
}
private static ChargeAdapter getChargeAdapter(DigitalAppliance digitalAppliance) {
for (ChargeAdapter chargeAdapter : CHARGE_ADAPTERS) {
// 判断是否适配
if (chargeAdapter.support(digitalAppliance)) {
return chargeAdapter;
}
}
throw new RuntimeException("没有合适的适配器");
}
}
2.2 类适配器模式
Iphone所期待的充电插口可以是接口也可以是抽象类或具体类。被适配类和适配器是父子关系,适配器作为能充苹果的Typec
2.2.1 类图
2.2.2 代码实现
// 被适配的类
public class TypeC {
public void charge() {
System.out.println("type-c充电....");
}
}
// 期望使用的接口
public interface IphoneChargeAdapter {
void chargeToIphone();
}
// 适配器,继承Typec,把自己当成Typec,但又可以充苹果
public class TypeCToIphoneAdapter extends TypeC implements IphoneChargeAdapter {
@Override
public void chargeToIphone() {
System.out.println("转换成iphone口....");
charge();
}
public static void main(String[] args) {
// 使用
IphoneChargeAdapter iphoneChargeAdapter = new TypeCToIphoneAdapter();
iphoneChargeAdapter.chargeToIphone();
}
}
2.3 对象适配器模式
被适配类和适配器是组合关系,作为适配器的属性存在。
2.3.1 类图
2.3.2 代码实现
public interface IphoneChargeAdapter {
void chargeToIphone();
}
public class TypeC {
public void charge() {
System.out.println("type-c充电....");
}
}
public class TypeCToIphoneAdapter implements IphoneChargeAdapter {
TypeC typeC;
public TypeCToIphoneAdapter(TypeC typeC) {
this.typeC = typeC;
}
@Override
public void chargeToIphone() {
System.out.println("转换成iphone口....");
typeC.charge();
}
public static void main(String[] args) {
TypeC typeC = new TypeC();
IphoneChargeAdapter adapter = new TypeCToIphoneAdapter(typeC);
adapter.chargeToIphone();
}
}
五、与装饰器模式的区别
装饰器模式的目的是在原有功能的基础之上增强扩展功能。而适配器模式的目的是将一个接口转变成另一个接口,改变原有接口的功能。
六、优点
- 提高了类的复用,低耦合
- 灵活性好,不想用适配器,直接删除就好,不会影响
- 较好的扩展性,符合开闭原则
原文: Java设计模式之适配器模式_吖土豆的博客-CSDN博客