Java设计模式之从[鼠标接口][星际争霸中的兵种行为]分析适配器(Adapter)模式

适配器将一个类的接口转换成客户希望的另外一个接口。下面用三个例子来反映适配器的不同用途:

  情况一:

  我买了一个PS2接口的鼠标,但是我的电脑没有PS2的接口,仅有USB的接口。为了不浪费这个鼠标,我跑到商店买了一个PS2到USB的转接头,这样我就用上了PS2的鼠标。USB转接头就是一个典型的适配器。

  1. interface USBPort {  
  2.     void connect();  
  3. }  
  4.   
  5. interface PS2Port {  
  6.     void connect();  
  7. }  
  8.   
  9. class USBMouse implements USBPort {  
  10.     public void connect(){  
  11.         System.out.println("鼠标连接上了USB端口!");  
  12.     }  
  13. }  
  14.   
  15. class PS22USBMouseAdapter implements USBPort{  
  16.     private USBPort usbMouse;  
  17.     public PS22USBMouseAdapter (USBPort usbPort){  
  18.         usbMouse = usbPort;  
  19.     }  
  20.     public void connect(){  
  21.         usbMouse.connect();  
  22.     }  
  23. }  
  24.   
  25. class Adapter1  
  26. {  
  27.     public static void main(String[] args) {  
  28.         USBMouse mouse = new USBMouse();  
  29.         mouse.connect();  
  30.         USBPort adapter = new PS22USBMouseAdapter(mouse);  
  31.         adapter.connect();  
  32.     }  
  33. }  


  PS22USBMouseAdapter是一个PS2到USB接口的适配器,由于它最终输出的是USB信息,因此继承了USBPort。我们最后实例 化adapter时,它的类型是USBPort —— 设计模式就是如此,我们一般用对象的抽象来进行声明和定义,而不是具体的类。PS22USBMouseAdapter实现了PS2接口向USB接口的转 变。

  情况二:

  星际争霸中,人族的顶级兵种为战斗巡洋舰(Battlecruiser)。巡洋舰上有个技能叫做大和炮(Yamato gun)。

  假设我们在设计巡洋舰的时候,并没有想到它可以装载大和炮,那么我们的巡洋舰类(Battlecruiser)中仅有一个attack方法。后 来我们希望给巡洋舰增加一个大和炮的技能,但是我们又不想修改巡洋舰类的代码,这个时候就可以用适配器来实现,此时的适配器可以理解成,我们在巡洋舰上装 一个转换装置,使得它可以安装和发射大和炮。

  1. class Battlecruiser{  
  2.     public void attack(){  
  3.         System.out.println("大和战舰发起进攻!");  
  4.     }  
  5. }  
  6.   
  7. class YamatoAdapter extends Battlecruiser implements Yamato {  
  8.     public void yamato(){  
  9.         System.out.println("大和战舰使用大和炮进行攻击!");  
  10.     }  
  11. }  
  12.   
  13. interface Yamato{  
  14.     void attack();  
  15.     void yamato();  
  16. }  
  17.   
  18. class Adapter2  
  19. {  
  20.     public static void main(String[] args) {  
  21.         Yamato superBattlecruiser = new YamatoAdapter();   
  22.         superBattlecruiser.attack();  
  23.         superBattlecruiser.yamato();  
  24.     }  
  25. }  


  注意,Battlecruiser类是我们一开始就设计好的。为了能给巡洋舰装上大和炮,我们新建了一个Yamato接口,这个接口有原来巡洋舰的 attack方法,并且还增加了一个yamato方法。最后,建立一个继承于巡洋舰的类YamatoAdapter,在测试类中用Yamato实例化一个 巡洋舰,它既可以普通攻击,又可以用大和炮进行攻击。

  你可能会想,明明YamatoAdapter已经继承了Battlecruiser,为何还要继承Yamato接口?原因如之前所说,我们用“接口”来定义对象,而不是用具体的类。

  情况三:

  我需要设计星际争霸人族兵种的一些抽象过程。如,所有兵种都要继承于一个接口,这个接口有attack、stop、move等方法。这也就意味着,任何一个兵种类都要实现attack、stop、move这三个方法。

  这样一来会有一个问题:并非所有的兵种都有attack、stop、move这3个行为。例如人族的医疗兵(Medic),她不具有 attack行为(游戏中她是无法攻击敌人的);再例如人族的秃鹰战车(Vulture,我们俗称的布雷车),它可以埋蜘蛛雷。蜘蛛雷在敌人靠近的时候, 它才会进行自爆攻击。也就是说,蜘蛛雷不具有stop和move方法,只具有attack方法。

  可见,一旦接口的方法多了起来,我们为了实现它们得手工写不少代码,要是其中若干方法是我们该类不会用到的,我们不得不写一个空方法。为了减少代码编写,这时,我们可以使用接口的适配器模式:

  1. interface StarcraftSoldier{  
  2.     void attack();  
  3.     void stop();  
  4.     void move();  
  5. }  
  6.   
  7. abstract class SoldierAdapter implements StarcraftSoldier {  
  8.     public void attack(){}  
  9.     public void stop(){}  
  10.     public void move(){}  
  11. }  
  12.   
  13. class SpiderMine extends SoldierAdapter {  
  14.     public void attack(){  
  15.         System.out.println("蜘蛛雷发现敌人,进攻!");  
  16.     }  
  17. }  
  18.   
  19. class Adapter3  
  20. {  
  21.     public static void main(String[] args) {  
  22.         new SpiderMine().attack();  
  23.     }  
  24. }  


  接口的适配器SoldierAdapter为接口StarcraftSoldier的所有方法做了空实现,在我们创建SpiderMine时,继承SoldierAdapter,就不必将接口中的所有方法都实现一次了。   以上就是我所理解的适配器的用途,我把它理解成一个兼容装置,或者转换装置。若有牵强的地方,欢迎大家指出。

 

 

Java设计模式之从[鼠标接口][星际争霸中的兵种行为]分析适配器(Adapter)模式,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。