适配器模式
适配器模式是一种使用频率非常高的结构型设计模式,如果在系统中存在不兼容的接口,可以通过引入一个适配器来使得原本因为接口不兼容二不能一起工作的两个类协同工作。
模式动机
我国的生活用电电压是220V,而笔记本电脑、手机等电子设备的电压都没有这么高。这时候就需要电源适配器,使得生活用电和笔记本电脑可以兼容。软件开发中采用类似电源适配器的设计和编码技巧被称为适配器模式。有时,现有类所提供的接口不一定是用户所期待的,使用适配器可以对现有接口请求转化为客户期望的接口请求。
模式定义
将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
模式结构
适配器模式包含如下角色:
-
Target(目标抽象类)
目标抽象类定义用户要用的特定领域的接口,可以是抽象类或接口,也可以是具体类;在类适配器中,由于Java语句不支持多重继承,它只能是接口。
-
Adapter(适配器类)
适配器类可以调用一个另一个接口,作为一个转换器,对Adaptee和Target进行适配。在类适配器中,它通过实现Target接口并继承Adaptee类使二者产生联系,在对象适配器中,通过继承Target并关联一个Adaptee对象使二者产生联系。
-
Adaptee(适配者类)
适配者即被适配角色,定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下甚至没有适配者类的源代码。
-
Client(客户类)
在客户类中针对目标抽象类进行编程,调用在目标抽象类中定义的业务方法。
类适配器模式
根据类适配器模式结构图,适配者类Adaptee没有request()方法,而客户期待这个方法,但Adaptee中实现了specificRequest()方法,该方法所提供的实现正是客户需要的。为了满足客户需要,适配器类Adapter实现抽象目标类接口并继承适配者类,适配器类request()方法调用所继承的适配者类的specificRequest()方法,实现适配的目的。
public class Adapter extends Adaptee implements Target {
public void request() {
specificRequest();
}
}
对象适配器模式
客户需求与上述相同,Adapter包装了一个适配者类,在适配器的request()方法中调用适配者的specificRequest()方法。
public class Adapter extends Target {
private Adaptee adaptee;
public Adapter() {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}
默认适配器模式
当不需要全部实现接口提供的方法时,可先设计一个抽象类实现该接口,并为接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类有选择地覆盖父类的某些方法实现需求。在默认适配器中包含三个角色,分别是适配者接口、默认适配器类和具体业务类。
-
适配者接口
适配者是被适配的对象,接口中声明了大量的方法
public interface ServiceInterface { public void serviceMethod1(); public void serviceMethod1(); public void serviceMethod1(); }
-
默认适配器类
默认适配器类使用空方法形式实现在接口中声明的方法
public abstract class AbstractServiceClass implements ServiceInterface { public void serviceMethod1(){}; public void serviceMethod1(){}; public void serviceMethod1(){}; }
-
具体业务类
具体业务类是默认适配器类的子类,根据需要有选择性地覆盖在适配器类中定义的方法
public class ConcreteServiceClass extends AbstractServiceClass { public void serviceMethod1(){ //具体实现 }; public void serviceMethod1(){ //具体实现 }; }
双向适配器
如果在适配器中同时包含对目标类和适配者类的引用,适配者可以通过它调用目标类中方法,目标类也可以通过它调用适配器类中方法,那么该适配器就是一个双向适配器。