适配器模式
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
定义:将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
适配器模式根据实现方式的不同分为类适配器模式**和***对象适配器模式***,以及***双向适配器模式***和***缺省适配器模式***。
###对象适配器模式
类图:
对象适配器模式结构图中包含如下几个角色:
● Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
● Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
● Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
看下代码实现:
假设这时我们手上有三孔的插座,我们插头是两孔插头,需要一个三孔转两孔的插头转换器。
第一步,创建一个目标抽象接口TwoHole,并用TwoHoleImpl实现这个接口。
package adapter;
public interface TwoHole {
void twoCharge();
}
package adapter;
public class TwoHoleImpl implements TwoHole {
@Override
public void twoCharge() {
System.out.println("使用两孔插座充电");
}
}
第二步,创建适配者类,即是三孔插座接口ThreeHole,并用ThreeHoleImpl实现这个接口。
package adapter;
public interface ThreeHole {
void threeCharge();
}
package adapter;
public class ThreeHoleImpl implements ThreeHole {
@Override
public void threeCharge() {
System.out.println("使用三孔插座充电");
}
}
第三步,创建一个适配器类ThreeSwitchTwoAdapter,也就是三孔转两孔的转换器。
package adapter;
//对象适配器模式
public class ThreeSwitchTwoAdapter implements ThreeHole {
private TwoHole twoHole;
//此适配器必须要有一个二孔的插口才能工作
public ThreeSwitchTwoAdapter(TwoHole twoHole) {
this.twoHole = twoHole;
}
@Override
public void threeCharge() {
twoHole.twoCharge();
}
}
第四步,创建一个具有三孔插座的酒店类Hotel。
package adapter;
public class Hotel {
//旅馆默认是三孔的充电器
private ThreeHole threeHole = new ThreeHoleImpl();
public void setSwitcher(ThreeHole threeHole) {
this.threeHole = threeHole;
}
//充电
public void charge() {
threeHole.threeCharge();
}
}
第五步,编写测试类。
package adapter;
public class ObjectAdapterTest {
public static void main(String[] args) {
//找了一个旅馆住下
Hotel hotel = new Hotel();
//如果你是三孔的充电器,开始充电,直接充电
hotel.charge();
//如果你带的是二孔的充电器,拿出二孔的充电器,发现没法充电
TwoHole twoHole = new TwoHoleImpl();
//适配器的构造函数,需要一个三孔转二孔的转换头
ThreeHole threeHole = new ThreeSwitchTwoAdapter(twoHole);
//这个时候将适配器插在旅馆的 三孔插座上
hotel.setSwitcher(threeHole);
//开始充电
hotel.charge();
}
}
第六步,查看输出
使用三孔插座充电
使用两孔插座充电
紧接着我们来看类适配器模式。
类适配器
类图:
在类适配器中,我们和对象适配器相比,只需要改变适配器类就可以了。
第一步,修改适配器类:
package adapter;
//类适配器,直接继承了所要适配的目标类型,并且实现转换者类,
//这样他的类型是转换者类型,但是可以直接使用super调用目标类的方法
public class ThreeSwitchTwoAdapter2 extends TwoHoleImpl implements ThreeHole {
//重写继承接口ThreeHole中的方法
@Override
public void threeCharge() {
super.twoCharge();
}
}
第二步,编写测试类:
package adapter;
public class ClassAdapterTest {
public static void main(String[] args) {
//找了一个旅馆住下
Hotel hotel = new Hotel();
//如果你是三孔的充电器,开始充电,直接充电
hotel.charge();
//适配器的构造函数,说我需要一个二孔的插头插在我上面
ThreeHole threeHole = new ThreeSwitchTwoAdapter2();
//这个时候将适配器插在旅馆的 三孔排插上
hotel.setSwitcher(threeHole);
//充电
hotel.charge();
}
}
第三步,输出:
使用三孔插座充电
使用两孔插座充电
总结,可以看出类适配器和对象适配器的区别就在于类适配器的重点在于类,是通过构造一个继承适配目标TwoHoleImpl类来实现适配器ThreeHole的功能;对象适配器的重点在于对象,是通过在直接包含适配目标TwoHoleImpl类来实现的,当需要调用特殊功能的时候直接使用适配者ThreeHole中包含的那个适配目标对象TwoHoleImpl来调用特殊功能的方法即可。