今天,我们来分享结构型模式的另外一个成员:适配器模式。
适配器模式是一种结构型模式,它允许接口不兼容的类能够一起工作,它通过创建一个中间适配器(Adapter)来实现这个功能。
其实,在平时生活或者工作中,我们经常能看到适配器的影子,比如:有些插头需要三口转2口。
又如有些国家电压是110v,而中国的电压是220v。如果要在中国使用外国110V的电器,需要有一个将电压从220v转化成110v的变压器才可以适配。又如,由于历史原因,多个项目中采用了多种不同的缓存操作,方法处理都不太一致,使用适配器可以将不同的缓存实现转换成同一种缓存实现,从而解决缓存兼容性的问题。
接下来,我们给出适配器模式的基本介绍以及相关的示例。
意图
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能再一起工作的那些类可以一起工作。
结构
适配器模式主要包含类适配器和对象适配器,当然,在某些场景中也有接口适配,主要是提供一些空实现,然后子类通过需要去重写即可。
类适配器模式
对象适配器模式
主要包含如下几个部分:
Target
定义Client使用的与特定领域相关的接口。
Adaptee
定义一个已经存在的接口,这个接口需要适配。
Adapter
对Adaptee的接口和与Target接口进行适配。
1、类适配器示例
比如:已有一个处理xml的接口,由于某些原因,老接口不再暴露,实现逻辑保留。同时,需要提供一个新的接口,包含xml和json的处理。
Adaptee (老接口实现)
老的接口如下:
Target (新的目标接口)
新的目标接口,具备2个方法一个处理xml,另外一个处理json。
Adapter - (类适配器)
写一适配器,继承老的功能实现(LegacyFunctionHandler),同时实现新的目标接口NewHanlder。
上述示例中,handleXml的方法本质是采用了老的实现,使用了super.handle(xmlString)来处理。当然,已经继承使用,super也可以改成this或者不写,都可以完成调用。
Client客户端
运行后输出内容:
这样,一个简单的类适配器实现就完成了。我们可以看到,类适配采用的是继承的方式实现。
问题来了?
如果适配器已有继承,不能再继承老的功能实现,怎么办?还能使用功能吗?
答案是肯定的。这个时候,我们可以采用对象适配模式。
2、对象适配器示例
我们还在是在上述示例中进行。改变适配器的写法,同时调整客户端Client的调用。
Adapter - (对象适配器)
对象适配器的写法,实现新的目标接口NewHanlder。其不再继承老的功能实现(LegacyFunctionHandler),采用的是类似构造函数之类的赋值,维护老功能实现的引用,然后通过委派的方式完成老功能方法的调用。
客户端Client
运行后输出内容:
这样,使用对象适配的写法就完成了。同样完成了一样的功能。我们可以看到,对象适配采用的是委派的方式实现。
接下来,我们再来看下接口适配器(缺省适配器)的示例。
3、接口适配示例
在开始示例之前,我们先来思考一个问题? 为什么要有缺省适配器模式呢?
在有些时候,一个接口可能定义多个方法,但是有些方法在某些实现中并不需要实现。那么,如果我们这个时候给出一个所有方法都有默认实现的基类,这样子类可以有选择地覆写方法,到达按需实现即可。
比如:监听文件或者目录的处理。
接口
缺省适配器写法
一般定义为抽象类,包含接口所有方法的默认实现。在本示例中,空方法不做任何处理。
自定义实现
根据需要,选择性地覆写接口即可 。
客户端Client
运行一下,输出结果:
onFileCreate - 自定义实现
这样,一个简单的缺省适配器写法就完成了。其实,这样写法很多,相信很多读者都遇到过。尤其是对AWT或者Swing有过编程的小伙伴。
更多缺省适配器示例:
1、鼠标事件缺省适配器
鼠标事件可以有很多的事件。如果只要其中的几个,继承抽象缺省适配器,然后覆写想要实现的事件接口即可,不需要每一个都实现一遍。
2、MDC适配器
并不是所有的日志系统都支持MDC (Mapped Diagnostic Context),使用一个默认实现的缺省适配器,在不支持MDC的日志系统上,也可以完成统一处理而不报错。
更多的示例,读者可以自行去发现和观察。
JDK中的适配器模式的影子
JDK提供了多个适配器模式的例子,如
java.util.Arrays#asList()
java.util.Collections#list()
java.util.Collections#enumeration()
java.io.InputStreamReader(InputStream)
(返回一个 Reader
)java.io.OutputStreamWriter(OutputStream)
(返回一 个 Writer
)适配器模式 vs. 桥接模式、装饰者模式
桥接模式 : 桥接模式通过组合的方式,将抽象部分和实现部分分离,并在它们之间建立一个桥接接口,从而使得抽象部分和实现部分可以独立地变化,而不会相互影响。
装饰器模式:使用一个装饰器类,将原有对象进行包装,并在包装对象上添加新的行为,从而实现动态地扩展原有对象的功能。
与适配器模式的区别: 桥接模式和装饰器模式都不会改变原有对象的接口,而适配器模式则是为了将一个不兼容的接口转换成另一个兼容的接口,从而使得原有对象可以被其他对象所使用。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。