什么是适配器模式?
- 就是把一个类的接口转换成客户端所期待的另一个接口,从而使原来接口不匹配而无法在一起工作的两个类能在一起工作
从功能上讲这些接口不兼容的类一般具有相同或相似的功能。通常我们通过修改该类的接口来解决这种接口不相同的情形,但是如果我们不愿意为一个应用修改各原有的接口,或者我们压根就没有对原有对象的源代码那该怎么办呢?此时Adapter模式就会派上大用场;
如果有两个编译好的(无源代码)类,类A有某些功能,但是需要一个xml读取模块才能工作,
这个模块要实现这个接口:
public interface XmlReader {
public InputStream xmlReader();
}
你的另一个类B恰好有这个功能,但是B实现的是这个接口:
public interface ReaderXml {
public InputStream readerXml();
}
这时候我们的做法是写个适配器:
public class Adapter extends B implements XmlReader {
public InputStream xmlReader(){
return readerXml();
}
}
或者另外一种实现方式
public class Adapter implements XmlReader{
ReaderXml b = new B();
public InputStream xmlReader(){
return b.readerXml();
}
}
就像生活中,你的朋友从美国帮你带回一个微波炉,但因为美国的生活用电电压是110V的,而中国的电压是220V的。所以这个微波炉在中国不能直接使用,但如果你再买一个变压器,这个时候把220V电压转换成110V电压,再接入微波炉,这时你就可以放心使用了。
适配器模式的几个要素----目标、客户、被适配者、适配器。
- 目标(CTarget):定义一个客户端使用的特定接口。
- 客户(CClient):使用目标接口,与和目标接口一致的对象合作。
- 被适配者(CAdaptee):一个现存需要匹配的接口。
- 适配器(CAdapter):负责将CAdaptee的接口装换成CTarget的接口
适配器是一个具体的类,这是本模式的核心,由此可见,当客户端调用Adapter接口的时候,Adapter便会调用Adaptee的操作相应请求,该模式就完成了接口的适配过程。
优势与缺陷
- 适配器模式可以将一个类的接口和另一个类的接口匹配起来,使用的前提是你不能或 不想修改原来的适配器母接口。例如,你向第三方购买了一些类、控件、但没有源程序,这时,使用设配器模式,你可以统一对象访问接口,但客户调用可能需要变动。
何时使用适配器模式
- 如果两个类所做的事情相同或相似,但是他们有不同的接口的时候要使用它。
- 就好像在设计一个系统时使用第三方开发组件,这个组件的接口与系统接口不相同,这时候就不用为了迎合它去改动自己的接口,这种情况下,虽然是开发设计阶段,解决接口不同的问题也可以用适配器模式。
适配器总体上分两类----类适配器和对象适配器
例如,系统中有一个具有某个特定功能的类Adaptee,一个客户类Client--他需要一个实现Target接口的对象,和一个Target接口:
public class Adaptee {
public void specialRequest(){
System.out.println("Called SpecificRequest() in Adaptee" );
}
}
public class Client {
public static void main (String[] args){
Target t = ....//new Adapter();
t.request();
}
}
public interface Target {
public void request();
}
根据以上的分析,我们知道此时需要一个Adapter对象,该对象实现Target接口,同时它又重用现有的Adaptee类,任何有一点OO(面向对象)知识的人都会想到通过继承可以达到重用的目的:
通过继承实现Adaptee类重用的例子(类适配器):
public class Adapter extends Adaptee implements Target {
public void request(){
this.specialRequest();
}
}
客户端调用Target接口的request方法,实际就是调用其父类Adaptee的specialRequest方法。
这就是类的适配器,类适配器具有以下两个特点:
- 适配器类(Adapter)实现Target接口
- 适配器类(Adapter)通过继承来实现对Adaptee类的重用。
通过组合关系实现继承的例子(对象适配器)
public class Adapter implements Target{
Adaptee adaptee = new Adaptee();
public void request(){
adaptee.specialRequest();
}
}
对于两者不同的设配器客户代码其实都是一样的:
public class Client {
public static void main (String[] args){
Target t = new Adapter();
t.request();
}
}
类适配器和对象适配器有什么不同呢?
- 类适配器是通过继承类适配者类(Adaptee Class)实现的,另外类适配器实现客户类所需的接口。当客户对象调用适配器类方法的时候,适配器内部调用它所继承的适配者的方法。
- 对象适配器包含一个适配器者的引用(reference),与类适配器相同,对象适配器也实现了客户类需要的接口。当客户对象调用对象适配器的方法的时候,对象适配器调用它所包含的适配器者实例的适当方法。