适配器模式有类的适配器模式和对象的适配器模式两种不同的形式,如下图所示,左边是类的适配器模式,右边是对象的适配器模式。
类的适配器模式:
以下是uml类图:
模式所涉及的角色有:
*目标(Target)角色:这就是所期待得到的接口。注意,由于这里讨论的是类适配器模式,因此目标不可以是类。
*源(Adaptee)角色:现有需要适配的接口。
*适配器(Adapter)角色:适配器类是本模式的核心,适配器把源接口转换成目标接口,显然,这一角色不可以是接口,而必须是具体类。
该模式的实现源码为:
Target:
package Adapter.ClassAdapter; public interface Target { /* * 这是源类也有的方法sampleOperation1 */ void sampleOperation1(); /* * 这是源类没有的方法sampleOperation2 */ void sampleOperation2(); }上面给出的是目标角色的源代码,这个角色是以一个java接口的形式实现的,可以看出,这个接口声明了两个方法:sampleOperation1()和
sampleOperation2()。而源角色Adaptee是一个具体类,它有一个sampleOperation1()方法,但是没有sampleOperation2()方法,如下所示:
Adaptee:
package Adapter.ClassAdapter; public class Adaptee { /* * 源类含有方法sampleOperation1 */ public void sampleOperation1(){} }适配器角色Adapter扩展了Adaptee,同时又实现了目标接口,由于Adaptee没有提供sampleOperation2()方法,而目标接口又要求这个方法,
因此适配器角色Adapter实现了这个方法,如下所示:
package Adapter.ClassAdapter; public class Adapter extends Adaptee implements Target{ /* * 由于源类没有方法sampleOperation2 * 因此适配器类补充上这个方法 * @see ClassAdapter.Target#sampleOperation2() */ public void sampleOperation2() { } }总结:
使用一个具体类把源(Adaptee)适配到目标(Target)中,这样一来,如果源以及源的子类都是用此类适配,就行不通了。
由于适配器类是源的子类,因此可以在适配器类中置换掉源的一些方法。
对象的适配器模式:
该模式所涉及到的角色为:
*目标(Target)角色:这是所期待的的接口,目标可以是具体的或抽象的类。
*源(Adaptee)角色:现有需要适配的接口。
*适配器(Adapter)角色:适配器是本模式的核心,适配器把源接口转换成目标接口,显然,这一角色必须是具体类。
源码如下:
Target:
package Adapter; public interface Target { /* * 这是源类也有的方法 sampleOpertion1 */ void sampleOperation1(); /* * 这是源类没有的方法sampleOperation2 */ void sampleOperation2(); }Adaptee:
package Adapter; public class Adaptee { /* * 源类有方法sampleOperation1 */ public void sampleOperation1(){} }Adapter:
package Adapter; public class Adapter implements Target { private Adaptee adaptee; public Adapter(Adaptee adaptee){ this.adaptee=adaptee; } /* * 源类有方法sampleOperation1因此适配器类直接委派即可 * @see Adapter.Target#sampleOperation1() */ public void sampleOperation1() { adaptee.sampleOperation1(); } /* * 源类没有方法sampleOperation2 * 因此由适配器类需要补充此方法 * @see Adapter.Target#sampleOperation2() */ public void sampleOperation2() { } }对象适配器模式的效果为:
*一个适配器可以把多种不同的源适配到同一个目标。换言之,同一个适配器可以把源类和它的子类都适配到目标接口。
*与类的适配器模式相比,要想置换源类的方法本来就不容易,如果一定要置换源类的一个或者多个方法,就只能先做一个源类的子类,
将源类的方法置换掉,然后再把源类的子类当做真正的源进行适配。
在什么情况下使用适配器模式:
(1)系统需要使用现有的类,而此类的接口不符合系统的需要。
(2)想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,
这些源类不一定有很复杂的接口。
(3)(对对象的适配器模式而言)在设计里,需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类
做一个适配器类,而这不太实际。