0.更新
- 2019-4-15完成,文章V1.0.0
- 2019-4-15更新了类适配器和对象适配模式的区别,添加了新标题思考和内容,更新了参考博客(添加了双向适配器的参考博客),文章V1.1.0
1.适配器模式概述
在现实生活中常常用到适配器模式,典型列子为转接口(转接器):生活用电为220V,笔记本电脑适合电压为20V,把220V转成20V就需要一个转接器把电压降低,手机同理。
同理,在软件开发中:存在不兼容的结构,例如方法名不一致,因此需要引入适配器模式
2.适配器模式定义
- 定义:又称包装器(Wrapper)模式,将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。
- PS:定义中所提及的接口是指广义的接口,它可以表示一个方法或者方法的集合。
3.适配器两种结构类型-类适配器和对象适配器
- 适配器模式包含以下3个角色:
Target(目标抽象类)
Adapter(适配器类)
Adaptee(适配者类)
1. 类适配器
- Adapter类继承Adaptee类并实现Target接口。
2. 对象适配器
- Adapter类继承Adaptee类并实现Target接口。
两者区别:对象适配器模式中适配器和适配者之间是关联关系,而类适配器模式中适配器和适配者是继承关系。
4.适配器模式(类适配器、对象适配器)优缺点以及适用场景
- 优点
- 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
- 增加了类的透明性和复用性,提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。
- 灵活性和扩展性非常好。
- 类适配器模式:置换一些适配者的方法很方便。
- 对象适配器模式:可以把多个不同的适配者适配到同一个目标,还可以适配一个适配者的子类。
- 缺点
-
类适配器模式:(1) 一次最多只能适配一个适配者类,不能同时适配多个适配者;(2) 适配者类不能为最终类;(3) 目标抽象类只能为接口,不能为类。
-
对象适配器模式:在适配器中置换适配者类的某些方法比较麻烦。
- 适用场景
-
**系统需要使用一些现有的类,**而这些类的接口不符合系统的需要,甚至没有这些类的源代码。
-
创建一个可以重复使用的类,用于和一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作。
5.适配器模式应用
现有一类Square中方法squ(float l)用于计算正方形的面积,现在要求有类Circle用于计算圆的内接正方形的面积,请用适配器模式实现该面积的输出,要求复用Square,请绘编码实现。
- 对象适配器方式实现
思路:把题目内容重点找出来带入对象适配器UML图
Target(目标抽象类):Target接口
Adapter(适配器类):Circle类
Adaptee(适配者类):Square类
public class Square {
public float squ(float f){//求正方形面积
return f*f;
}
}
public interface Target { //目标接口
public float squ(float f);
}
public class Circle implements Target{//实现接口方法,这就是你想用的类
Square ada = new Square();//创建适配者类,即想要复用的类
public float squ(float f){
return ada.squ(f)/2;//调用适配者类接口方法,内接正方形:r*r/2
}
}
测试一下
public class Main {
public static void main(String args[]) {
Circle circle = new Circle();
float f = 8;
float s = circle.squ(f);
System.out.println(s);
}
}
//输出32.0
- 类适配器方式实现
思路:同样是分析题目并把内容带入类适配器UML图
public class Circle extends Square implements Target{ //Target接口和Square类同上
public float squ(float f){
return super.squ(f)/2;
}
}
测试一下
public class Main {
public static void main(String args[]) {
Circle circle = new Circle();
System.out.println(circle.squ(8));
//输出32.0
}
}
//输出32.0
6.思考
在对象适配器中,一个适配器能否适配多个适配者?如果能,应该如何实现?如果不能,请说明原因?如果是类适配器呢?
- 一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
- 类适配器一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
7.参考博客
博主 峰峰峰峰峰:一起学设计模式 - 适配器模式
https://segmentfault.com/a/1190000011856448
博主 人生如若初见: 适配器模式的两种实现方式 (ps:包括缺省适配器)
https://www.cnblogs.com/winkey4986/p/5482064.html
博主 刘伟:不兼容结构的协调——适配器模式(三)
https://blog.csdn.net/lovelion/article/details/8624428