适配器模式
适配器模式说的是,可以把一个类的接口变换成客户端所期待的另一种接口,使得原本因接口不匹配而无法在一起工作的两个类可以一起工作。
适配器模式的用途
适配器模式的用途,在网上找了一幅图,挺形象的:
比方说我有一个台灯,其插头是标准的两相的交流电插头,即阳极、阴极。我旅游到了一个地方想用自己的台灯,但发现旅馆里面只有三相的插头,即在阳极、阴极的基础上还多了一个地级。这时候怎么办呢,一个两相到三相的转换器(适配器)就能解决这个问题了,而这正是本模式所做的事情。
类适配器
适配器模式分两种,类适配器和对象适配器。先讲类适配器,类适配器把适配的类的API转换成目标类的API,类适配器所涉及的角色有:
1、目标角色
这是所期待得到的接口
2、源角色
现在需要适配的接口
3、适配器角色
模式的核心,适配器把源接口转换成目标接口
类适配器示例
目标接口,期待得到sampleOperation1()和sampleOperation2()两个方法:
public interface ClassTarget { /** 这是源类ClassAdaptee也有的方法 */ public void sampleOperation1(); /** 这是源类ClassAdaptee没有的方法 */ public void sampleOperation2(); }
源角色,只有一个sampleOperation1()方法:
public class ClassAdaptee { public void sampleOperation1(){} }
适配器角色扩展了ClassAdaptee,同时又实现了目标接口。由于ClassAdaptee没有提供sampleOperation()2方法,而目标接口又要求这个方法,因此适配器角色实现了这个方法:
public class ClassAdapter extends ClassAdaptee implements ClassTarget { public void sampleOperation2() { // 相关代码 } }
可能有些人一遍看下来不是很明白,这怎么就是一个适配器模式了,解释一下:
1、客户端期待一个接口ClassTarget有sampleOperation1()和sampleOperation2()这两个方法
2、现在我一个类ClassAdaptee里面只有一个sampleOperation1()方法
3、既然ClassTarget要两个方法,我现在的ClassAdaptee只有一个方法怎么办?搞一个适配器,多变出一个sampleOperation2(),就符合ClassTarget的标准了,由于适配器是ClassTarget接口的实现类,所以可以直接使用适配器作为ClassTarget
对象适配器示例
还是一样的,一个目标接口,期待得到sampleOperation1()和sampleOperation2()方法:
public interface ObjectTarget { public void sampleOperation1(); public void sampleOperation2(); }
源角色,只有一个sampleOperation1()方法:
public class ObjectAdaptee { public void sampleOperation1(){} }
和类适配器不同的是,对象适配器采用了委派关系将源角色与适配器角色关联:
public class ObjectAdapter { private ObjectAdaptee objectAdaptee; public ObjectAdapter(ObjectAdaptee objectAdaptee) { this.objectAdaptee = objectAdaptee; } public void sampleOperation1() { this.objectAdaptee.sampleOperation1(); } public void sampleOperation2(){} }
适配器模式在JDK中的应用及解读
写了这么多种设计模式了,可能适配器模式是最不好理解的一种写法。适配器模式的写法很多,写法越多、模式越不好理解,就越应该抓住模式的核心,像适配器模式的核心就是"把一个类的接口变换成客户端所期待的另一种接口",所以我们可以看一下InputStreaReader和OutputStreamWriter。
比方说InputStreamReader吧,创建InputStreamReader对象的时候必须在构造函数中传入一个InputStream实例,然后InputStreamReader的作用就是将InputStream适配到Reader。很显然,适配器就是InputStreamReader,源角色就是InputStream代表的实例对象,目标接口就是Reader类。
OutputStreamWriter也是类似的方式。
适配器模式的优缺点
优点
1、有更好的复用性。系统需要使用现有的类,但此类接口不符合系统需要,通过适配器模式让这些功能得到很好的复用
2、有更好的扩展性。实现适配器,可以调用自己开发的功能
缺点
过多使用适配器会使得系统非常凌乱,明明调用的是A接口,内部却被适配成了B接口。因此除非必要,不推荐使用适配器,而是直接对系统重构