适配器模式的定义:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
适配器模式其实也可以叫做转换器模式,由定义可知适配器其实就是包装某些对象从而让他们的几口开起来不像自己而像是别的东西。举一个简单的例子 :
假设现在已有一个软件系统,你希望它能和一个新的厂商类库搭配使用,但是这个新厂商所设计出来的接口不同于旧厂商的接口,如下图所示:
此时如果不想改变现有代码解决这个问题,就可以重新写一个类,这个类负责将新厂商接口转接成你所期望的接口,这个类就是一个适配器:
这个适配器实现了你的类所期望的接口,而且这个适配器也能和厂商的接口沟通,这个适配器工作起来就如同一个中间人,它将客户所发出的请求转换成厂商类能理解的请求,这就是适配器模式。
再通过代码的例子来详细了解一下这个模式,现在有一个鸭子和火鸡的接口声明如下:
public interface Duck {
public void quack();
public void fly_long();
}
public interface Turkey {
public void gobble();
public void fly_short();
}
实现一个具体的鸭子和火鸡类
public class MallardDuck implements Duck {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("Quack!");
}
@Override
public void fly_long() {
// TODO Auto-generated method stub
System.out.println("I'm flying!");
}
}
public class WildTurkey implements Turkey {
@Override
public void gobble() {
// TODO Auto-generated method stub
System.out.println("Gobble!");
}
@Override
public void fly_short() {
// TODO Auto-generated method stub
System.out.println("I'm flying a short distance");
}
}
现在假设你缺少鸭子对象,想用一些火鸡对象来冒充,显而易见因为火鸡的接口不同,所以不能直接拿来用,所以写个适配器类完成这个转化过程:
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
@Override
public void quack() {
// TODO Auto-generated method stub
turkey.gobble();
}
@Override
public void fly_long() {
// TODO Auto-generated method stub
for (int i = 0; i < 5; i++) {//变成能够长距离飞行
turkey.fly_short();
}
}
}
测试一下:
public class DuckTestDriver {
public static void main(String[] args) {
// TODO Auto-generated method stub
MallardDuck duck = new MallardDuck();
WildTurkey turkey = new WildTurkey();
Duck turkeyAdapter = new TurkeyAdapter(turkey);
System.out.println("The Turkey says...");
turkey.gobble();
turkey.fly_short();
System.out.println("\nThe Duck says...");
testDuck(duck);
System.out.println("\nThe TurkeyAdapter says...");
testDuck(turkeyAdapter);//这里的鸭子其实是一个火鸡冒充的
}
static void testDuck(Duck duck) {
duck.quack();
duck.fly_long();
}
}
打印结果:
The Turkey says...
Gobble!
I'm flying a short distance
The Duck says...
Quack!
I'm flying!
The TurkeyAdapter says...
Gobble!
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
总之:
(1)当需要使用一个现有的类而其接口并不符合你的需要时,就使用适配器,适配器改变接口以符合客户的期望。
(2)实现一个适配器可能需要一番功夫,也可能不费功夫,视目标接口的大小与复杂度而定(为什么这么说是因为适配器并不是只能包装一个类尽管上边的例子确实只包装了一个火鸡类,可以通过适配器来适配许多类来提供一个接口让客户编码)。