还记得之前学的装饰者模式,是将对象包装起来,赋予它们新的职能。而这一篇要学的适配器模式目的相反,包装某些对象,让他们的接口看起来不像自己而像是别的东西。因为这样就可以在设计中,将类的接口转换成想要的接口。下面就来具体看看。
场景描述
先说一说现实中的场景最典型的一个适配器场景,就是插座。我们国内的、欧洲的、美国的插座可能都不一样,出国的时候买的转接头,就是适配器。比如去欧洲,它插在国内的插头和欧洲的插座之间,不用改任何一方就实现了适配。这里的话,用策略模式的鸭子们来模拟一个场景,假设需要很多鸭子对象,鸭子不够了。手边有一个新的物种,火鸡,它有自己的接口。因为火鸡的接口不同,所以我们不能公然拿来用,那我们看下适配器模式在这个场景下是如何工作的。
代码示例
简单的火鸡适配鸭子的场景
鸭子接口,以及实现
12345public interface Duck {public void quack();public void fly();}1234567891011public class MallardDuck implements Duck {public void quack() {System.out.println("Quack");}public void fly() {System.out.println("I'm flying");}}火鸡接口,以及实现
12345public interface Turkey {public void gobble();public void fly();}1234567891011public class WildTurkey implements Turkey {public void gobble() {System.out.println("Gobble gobble");}public void fly() {System.out.println("I'm flying a short distance");}}实现火鸡适配器,需要实现想转换成的类型接口,这里就是鸭子
1234567891011121314151617181920212223242526272829public class TurkeyAdapter implements Duck {/*** 适配器对象*/Turkey turkey;public TurkeyAdapter(Turkey turkey) {this.turkey = turkey;}/*** 将gobble接口转换成quack接口*/public void quack() {turkey.gobble();}/*** 虽然两个接口都具备fly行为,但是火鸡飞行距离短* 假设火鸡连续飞5次跟鸭子一样*/public void fly() {for (int i = 0; i < 5; i++) {turkey.fly();}}}测试
1234567891011121314151617181920212223public class Test {public static void main(String[] args) {MallardDuck duck = new MallardDuck();WildTurkey turkey = new WildTurkey();Duck turkeyAdapter = new TurkeyAdapter(turkey);System.out.println("The Turkey says...");turkey.gobble();turkey.fly();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();}}
总结
这个模式看似还挺简单的,重点是要回顾下适配器模式和装饰模式的区别。从目的上来说的话:装饰模式是不改变接口,但是添加责任,就是那种配料无限装饰奶茶,算出价格;适配器模式则是将一个接口转换成另一个接口,就好比这里的硬把火鸡转换成鸭子给客户使用。最后,要引出一种新模式,这个模式的目的是改变接口,但是它改变接口的原因是为了简化接口。这个模式被巧妙地命名为外观模式(Facade),之所以这么称呼,是因为它将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外观。外观模式我们下一章节再学习。