适配器模式
一、定义
适配器模式(Adapter Pattern):结构型模式的一种,把一个类的接口变成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。
二、分类
类适配器、对象适配器、接口适配器
三、角色
- Target(目标接口):该角色把其他类转换为我们期望的接口
- Adaptee (被适配者): 原有的接口,也是希望被改变的接口
- Adapter(适配器):将被适配者和目标接口组合到一起的类
四、类图
1) 类适配器:使用组合
2) 对象适配器
3) 接口适配器
接口适配器的使用场景: 原有接口有很多方法,而我们只需要其中一部分,这是看可以用抽象类来实现该接口,不需要的方法只需要写个空方法(默认实现)就好了,接口目标类去实现自己需要的接口
适用的场景是不想实现原有类的所有方法
二、示例
- 背景:使用小米 Micro USB 接口 为华为 Type-c 接口的手机充电
- 冲突:充电器接口时小米 Micro USB 的,手机接口是 Type-c 的,手机接口存在冲突
- 解决方案:设置一个适配器,代替转接口,使用 Micro USB 为华为手机充电
1) 类适配器
-
首先定义一个MicroCharger 类,表示Micro USB 的充电器,提供电源
/** * 提供电源的 Micro 接口的充电器 */ public class MicroCharger{ public void connection(){ System.out.println("使用 Mirco USB 充电"); } }
-
定义华为手机客户端使用的接口,业务相关
/** * 定义华为手机使用的接口 -> Type-c */ public interface Target { void connection(); } class TypeCDataLine implements Target { @Override public void connection() { System.out.println("使用Type-c充电器为手机充电"); } }
-
创建适配器类,继承被适配类,同时实现接口。
/** * 创建类适配器,继承了被适配类,同时实现标准接口 */ public class TypeCDataLineAdapter extends MicroCharger implements Target { @Override public void connection() { System.out.println("Micro to type-c 转接头"); super.connection(); } }
-
测试代码
public static void main(String[] args) { Target target = new TypeCDataLine(); target.connection(); TypeCDataLineAdapter typeCDataLineAdapter = new TypeCDataLineAdapter(); typeCDataLineAdapter.connection(); }
结果如下:
2) 对象适配器
/**
* 创建适配器类,实现标准接口,将这个调用委托给实现新接口的对象来处理
*/
public class TypeCDataLineAdapter implements Target {
private Target target;
public TypeCDataLineAdapter(Target target) {
this.target = target;
}
@Override
public void connection() {
System.out.println("Micro to type-c 转接头");
target.connection();
}
}
-
测试
public static void main(String[] args) { // 使用特殊功能类,即适配类 TypeCDataLineAdapter typeCDataLineAdapter = new TypeCDataLineAdapter( new TypeCDataLine() ); typeCDataLineAdapter.connection(); }
3) 区别:
- 类适配器:对象继承的方式,静态的定义。
- 对象适配器:依赖于对象的组合,都是采用对象组合的方式,也就是对象适配器实现的方式。
三、总结
优点
- 可以让任何两个没有关联的类一起运行
- 提高了类的复用,想使用现有的类,而此类的接口标准又不符合现有系统的需要。通过适配器模式就可以让这些功能得到更好的复用。
- 增加了类的透明度,客户端只关注结果
- 使用适配器的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
缺点
- 过多使用会导致系统凌乱,追溯困难(内部转发导致,调用A适配成B)
适用场景
- 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。
- 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。