适配器模式(Adapter Pattern) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
角色介绍目标(Target)角色:这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。
源(Adapee)角色:现在需要适配的接口。
适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。
分类:类适配器和对象适配器
类适配器: 具体实现: 类适配器模式/**
* Target角色
*/
public interface FiveVolt {
public int getVolt5();
}
/**
- Adaptee角色,需要被转换的对象
*/
public class Volt220 {
public int getVolt220() {
return 220;
}
}
// adapter角色
public class ClassAdapter extends Volt220 implements FiveVolt {
@Override
public int getVolt5() {
return 5;
}
}
Target角色给出了需要的目标接口,而Adaptee类则是需要被转换的对象。Adapter则是将Volt220转换成Target的接口。对应的是Target的目标是要获取5V的输出电压,而Adaptee即正常输出电压是220V,此时我们就需要电源适配器类将220V的电压转换为5V电压,解决接口不兼容的问题。
public class Test {
public static void main(String[] args) {
ClassAdapter adapter = new ClassAdapter();
System.out.println("输出电压 : " + adapter.getVolt5());
}
}
对象适配器:
对象适配器的具体实现
与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成为目标类的API,与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用代理关系连接到Adaptee类。
Adaptee类 ( Volt220 ) 并没有getVolt5()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,需要提供一个包装类Adapter。这个包装类包装了一个Adaptee的实例,从而此包装类能够把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。
示例代码如下 :
/**
- Target角色
*/
public interface FiveVolt {
public int getVolt5();
}
/**
- Adaptee角色,需要被转换的对象
*/
public class Volt220 {
public int getVolt220() {
return 220;
}
}
// 对象适配器模式
public class ObjectAdapter implements FiveVolt {
Volt220 mVolt220;
public ObjectAdapter(Volt220 adaptee) {
mVolt220 = adaptee;
}
public int getVolt220() {
return mVolt220.getVolt220();
}
@Override
public int getVolt5() {
return 5;
}
}
注意,这里为了节省代码,我们并没有遵循一些面向对象的基本原则。
使用示例 :public class Test {
public static void main(String[] args) {
ObjectAdapter adapter = new ObjectAdapter(new Volt220());
System.out.println("输出电压 : " + adapter.getVolt5());
}
}
模式结构:
适配器模式包含如下角色:
Target:目标抽象类
Adapter:适配器类
Adaptee:适配者类
Client:客户类
适配器模式有对象适配器和类适配器两种实现: 对象适配器: 优点:1.将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
2.增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
3.灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
类适配器模式还具有如下优点:由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
对象适配器模式还具有如下优点:一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点: 类适配器模式的缺点如下:对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
对象适配器模式的缺点如下:与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。