适配器模式
基本介绍
适配器模式(Adapter Pattern)是将某个类的接口转换成客户端期望的另一个接口表示,主要目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)。
适配器模式属于结构型模式,主要分为三类:类适配器模式、对象适配器模式、接口适配器模式
适配器模式的三个角色
- Target:目标类,最终要从
Adapter
输出的类。 - Adapter:适配器类
- Adaptee:被适配的类
类适配器模式
类适配器模式主要是通过 Adapter
类继承Adaptee
类,然后再实现Target
类接口,完成Adaptee
->Adapter
的转换。
举一个栗子
对手机进行充电,将 220V 的电压转换成5V 的电压进行充电。
类图分析
代码
Adaptee:
package cn.personalweb.adapter;
public class Adaptee {
/**
* 输出 220V 电压
* @return 220V 电压
*/
public int output220V() {
return 220;
}
}
Target:
package cn.personalweb.adapter;
public interface Target {
/**
* 输出 5V 电压
* @return 5V 电压
*/
public int output5V();
}
Adapter
package cn.personalweb.adapter;
public class Adapter extends Adaptee implements Target{
public int output5V() {
// 获取被适配者的输出电压
int adapteeVoltage = output220V();
// 进行转换适配,转换成目标的 5V 电压
int targetVoltage = adapteeVoltage / 44;
return targetVoltage;
}
}
Phone:
package cn.personalweb.adapter;
public class Phone {
public void charging(Target target) {
if (target.output5V() == 5) {
System.out.println("可以充电!");
} else {
System.out.println("电压不为 5V, 不能充电!");
}
}
}
Client
package cn.personalweb.adapter;
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new Adapter());
}
}
类适配器的注意事项和细节
- Java 是单继承机制,所以类适配器需要继承
Adaptee
类,这算是一个缺点,因为这个要求Target
必须是接口,有一定的局限性。 Adaptee
类的方法在Adapter
中会暴露出来,也增加了使用的成本。- 由于
Adapter
类继承了Adaptee
类,所以他可以根据需要重写Adaptee
类的方法,使得Adapter
更加灵活。
对象适配器模式
对象适配器模式的基本思路和类适配器模式相同,只是将Adapter
类做修改,类适配器模式是Adapter
继承Adaptee
,而在对象适配器中,是将继承改为聚合,以解决兼容性问题。
根据“合成复用原则”,在系统中尽量使用关联关系(聚合)来代替继承关系,所以对象适配器模式是适配器模式中最常用的一种。
类图分析:
代码
Adaptee:
package cn.personalweb.adapter;
public class Adaptee {
/**
* 输出 220V 电压
* @return 220V 电压
*/
public int output220V() {
return 220;
}
}
Target:
package cn.personalweb.adapter;
public interface Target {
/**
* 输出 5V 电压
* @return 5V 电压
*/
public int output5V();
}
Adapter
package cn.personalweb.adapter;
public class Adapter implements Target{
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public int output5V() {
int targetVoltage = 0;
if (null != adaptee) {
// 获取被适配者的输出电压
int adapteeVoltage = adaptee.output220V();
// 进行转换适配,转换成目标的 5V 电压
targetVoltage = adapteeVoltage / 44;
}
return targetVoltage;
}
}
Phone:
package cn.personalweb.adapter;
public class Phone {
public void charging(Target target) {
if (target.output5V() == 5) {
System.out.println("可以充电!");
} else {
System.out.println("电压不为 5V, 不能充电!");
}
}
}
Client
package cn.personalweb.adapter;
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new Adapter(new Adaptee()));
}
}
对象适配器模式注意事项和细节
对象适配器和类适配器其实是同一种思想,只不过实现方式不同。
根据“合成复用”原则,使用组合替代继承,所以他解决了类适配器必须继承Adaptee
的局限性问题,也不再要求Target
必须是接口。使用成本更低,更灵活。
接口适配器模式
接口适配器模式也称为缺省适配器模式。核心思路是当不需要全部实现接口提供的方法时,可以设计一个抽象类空实现接口的所有方法,抽象类的子类可以选择性地覆盖父类的一些方法,来实现自己的需求。
这种方法适用于一个接口不想使用其全部方法的情况。
栗子
Interface
package cn.personalweb.adapter;
public interface Interface4 {
public void m1();
public void m2();
public void m3();
public void m4();
}
AbsAdapter
package cn.personalweb.adapter;
public abstract class AbsAdapter implements Interface4{
// 空实现所有方法
public void m1() {
}
public void m2() {
}
public void m3() {
}
public void m4() {
}
}
Client
package cn.personalweb.adapter;
public class Client {
public static void main(String[] args) {
AbsAdapter absAdapter = new AbsAdapter() {
@Override
public void m2() {
System.out.println("是用了 m2方法");
}
};
absAdapter.m2();
}
}
参考资料:
尚硅谷 Java 设计模式课程笔记。