适配器模式
适配器模式把一个类的接口转换成客户端所期待的另一个中接口,使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
一个电器的例子
现在有一个电器,电器自带的插头是两脚的,但是现在只有三孔的插排,所以需要一个中间的适配器进行适配:
先写两个接口:
/**
*
* 源角色,两脚插头 Target
*/
public interface Plug2 {
//插头插入两孔插排方法
void in2();
}
/**
*
* 目标角色Adaptee
*/
public interface Plug3 {
void in3();//插入3孔插排方法
}
如何让这个两脚插头能插入到三孔的插排呢,这个适配器可以做到,它实现了源角色,并保持了一个三脚插头的引用
/**
*
* 适配器角色, Adapter
*/
public class Plug2Adapter implements Plug2{
Plug3 plug3;
public Plug3Adapter(Plug3 plug3){
this.plug3 = plug3; //保持对三脚插头的引用
}
@Override
public void in2() {
plug3.in3();
}
}
好了,写一个具体的三脚插头测试一下
//具体的三脚插头
public class SiemensPlug3 implements Plug3{
@Override
public void in3() {
System.out.println("西门子的三脚插头插入三孔插排。");
}
}
/**
*
* 客户端调用
*/
public class Client {
public static void main(String[] args) {
Plug2Adapter adapter = new Plug2Adapter(new SiemensPlug3());
adapter.in2(); //调用的是两脚插头的方法,但是实际上执行的是插入三孔插排
}
}
这个适配器是对象适配器,Adapter和Apaptee 是属于委派关系,而类适配器是继承关系。
缺省的适配器
讲一个鲁智深的故事
一个和尚都需要做什么呢?吃斋、念经、打坐、撞钟、习武。下面是一个和尚的接口:
public interface 和尚 {
void 吃斋();
void 念经();
void 打坐();
void 撞钟();
void 习武();
}
鲁智深实现和尚接口
public class 鲁智深 implements 和尚{
public void 习武(){
拳打镇关西;
倒把垂杨柳;
火烧瓦官寺;
}
}
这样的话程序编译不过去的,因为实现了和尚接口所以必须实现和尚接口的所有方法,而鲁智深从来不打坐念经,不需要实现这些方法。怎么解决呢?
《java与模式》中是这样说的:
以史为鉴,可以知天下。当初鲁达剃度,众僧说:“这个人形容丑陋,相貌凶顽,不可剃度他”,但是长老却说:“此人上应天星,心地刚直。虽然时下凶顽,命中驳杂,久后却得清净。证果非凡,汝等皆不及他”。
使用OO语言来说,“应”者,实现也;“天星”者,抽象类也。
public abstract class 天星 implements 和尚{
public void 吃斋(){}
public void 念经(){}
public void 打坐(){}
public void 撞钟(){}
public void 习武(){}
}
public class 鲁智深 extends 天星{
public void 习武(){
拳打镇关西;
倒把垂杨柳;
火烧瓦官寺;
}
}
这个抽象的天星类就是一个适配器类。
缺省的适配器的类图是这样的: