适配器模式无论是在生活中的场景还是框架的底层代码实现里都有大量的运用,属于结构型模式比较常用的@mikechen
适配器模式的定义
适配器模式(Adapter)的定义如下:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
在现实生活中,经常出现两个对象因接口不兼容而不能在一起工作的实例,这时需要第三者进行适配(转换)。
比如:美版和港版电脑的插头与国行不一样,所以我们需要更换电源适配器,或者增加一个转换插头来解决问题。
适配器模式的模型
适配器模式(Adapter)包含以下主要角色:
1.目标(Target)接口
当前系统业务所期待的接口,它可以是抽象类或接口。
2.适配者(Adaptee)类
它是被访问和适配的现存组件库中的组件接口。
3.适配器(Adapter)类
它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
适配器模式的实现
1.对象适配器
1)创建目标接口
package com.mikechen.java.design.adapter.model.objectadapter; /** * 目标接口 * * @author mikechen */ public interface Target { //源类有此方法 void sampleOperation1(); //源类无此方法 void sampleOperation2(); }
2)创建被适配的类
package com.mikechen.java.design.adapter.model.objectadapter; /** * 被适配的类 * * @author mikechen */ public class Adaptee { //源类有此方法 public void sampleOperation1(){} }
3)创建适配器
package com.mikechen.java.design.adapter.model.objectadapter; /** * 适配器 * * @author mikechen */ public class Adapter implements Target { //源 private Adaptee adaptee; public Adapter(Adaptee adaptee) { super(); this.adaptee = adaptee; } /** * 源类Adaptee有方法sampleOperation1 * 因此适配器类直接委派即可 */ @Override public void sampleOperation1() { adaptee.sampleOperation1(); } /** * 源类没有此方法 * 适配器类补充此方法 */ @Override public void sampleOperation2() { //重写方法 } }
2.类适配器
1)创建目标接口
package com.mikechen.java.design.adapter.model.classadapter; /** * 目标接口 * * @author mikechen */ public interface Target { //这是源类Adaptee也有的方法 void sampleOperation1(); //这是源类Adapteee没有的方法 void sampleOperation2(); }
2)创建被适配的类
package com.mikechen.java.design.adapter.model.classadapter; /** * 被适配的类 * * @author mikechen */ public class Adaptee { public void sampleOperation1(){} }
3)创建适配器
package com.mikechen.java.design.adapter.model.classadapter; /** * 适配器 * * @author mikechen */ public class Adapter extends Adaptee implements Target { /** * 源类没有方法sampleOperation2, * 因此适配器类补充上这个方法 */ @Override public void sampleOperation2() { //重写方法 } }
适配器模式的优缺
1.优点
1)更好的复用性
系统需要使用现有的类,而此类的接口不符合系统的需要,那么通过适配器模式就可以让这些功能得到更好的复用。
2)透明、简单
客户端可以调用同一接口,因而对客户端来说是透明的。
3)更好的扩展性
在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
4)解耦性
将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
5)符合开放-关闭原则
同一个适配器可以把适配者类和它的子类都适配到目标接口,可以为不同的目标接口实现不同的适配器,而不需要修改待适配类。
2.缺点
过多的使用适配器,会让系统非常零乱,不易整体进行把握。
适配器模式的应用场景
1.封装有缺陷的接口设计
假设我们依赖的外部系统在接口设计方面有缺陷(比如包含大量静态方法),引入之后会影响到我们自身代码的可测试性。
为了隔离设计上的缺陷,我们希望对外部系统提供的接口进行二次封装,抽象出更好的接口设计,这个时候就可以使用适配器模式了。
2.统一多个类的接口设计
某个功能的实现依赖多个外部系统,通过适配器模式,将它们的接口适配为统一的接口定义,然后我们就可以使用多态的特性来复用代码逻辑。
3.替换依赖的外部系统
把项目中依赖的一个外部系统替换为另一个外部系统的时候,利用适配器模式,可以减少对代码的改动。
4.兼容老版本接口
在做版本升级的时候,对于一些要废弃的接口,不直接将其删除,而是暂时保留,并且标注为 deprecated,并将内部实现逻辑委托为新的接口实现。
这样做的好处是,让使用它的项目有个过渡期,而不是强制进行代码修改,这也可以粗略地看作适配器模式的一个应用场景。
5.适配不同格式的数据
适配器模式主要用于接口的适配,实际上,它还可以用在不同格式的数据之间的适配。
比如,把不同格式的数据,统一为相同的格式, 也可以看作一种数据适配器,以方便存储和使用。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》