歡迎您光臨本站 註冊首頁

實例講解JAVA 適配器模式

←手機掃碼閱讀     月球人 @ 2020-06-26 , reply:0

在講述這個模式之前,我們先看一個案例:中國球員去NBA打籃球

中國球員去NBA打籃球,可是他不懂英語,所以聽不懂教練安排的戰術,所以現在有三種解決方式

1、球員學會英語。2、教練學會中文。3、請個翻譯。

1和2是長久之計,但不能解決迫在眉睫的問題。請個翻譯是短暫的更好的選擇。

放在軟件設計層面上,這就叫做適配器模式。

將一個類的接口轉換成客戶希望的另外一個接口。適配器模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。

在軟件開發中,也就是系統的數據和行為都正確,但接口不符時,我們應該考慮用適配器,目的是使控制範圍之外的一個原有對象與某個接口匹配,適配器模式主要應用於希望複用一些現存的類,但是接口又與複用環境要求不一致的情況。

在 GoF 的設汁模式中,對適配器模式講了兩種類型,類適配器模式和對象適配器模式,由於類適配器模式通過多重繼承對一個接口與另一個接口進行匹配,而JAVA語言不支持多重繼承,也就是一個類只有一個父類,所以我們這裡主要講的是對象適配器。

Target(這是客戶所期待的接口。目標可以是具體的或抽象的類,也可以是接口)代碼如下:

  public class Target {   public void request() {   System.out.println("普通請求");   }  }

 

Adaptee(需要適配的類)代碼如下:

  public class Adaptee {   public void specialRequest(){   System.out.println("特殊請求");   }  }

 

Adapter(通過在內部包裝一個Adaptee對象,把原接口轉換成目標接口)代碼如下:

  public class Adapter extends Target{   private Adaptee adaptee = new Adaptee();//建立一個私有的Adaptee對象      @Override   public void request() {   //這樣就可以把表面上調用request()方法變成實際調用的specialRequest()   adaptee.specialRequest();   }  }

 

測試方法

  public class Test {   public static void main(String[] args) {       //對main方法來說,調用的就是Target的request()        Target target = new Target();   target.request();   }  }

 

看起來是不是很簡單,是不是跟一句俗語很像“掛羊頭賣狗肉”。

何時使用適配器模式?

在想使用一個已經存在的類,但如果它的接口,也就是它的方法和你的要求不相同時,就應該考慮用適配器模式。兩個類所做的事情相同或相似,但是具有不同的接口時要使用它。而且由於類都共亨同一個接口,代碼可以統一調用同一接口就行了,這樣應該可以更簡單、更直接、更緊湊。

其實用適配器模式也是無奈之舉,很有點‘亡羊補牢'的感覺,沒辦法呀,是軟件就有維護的一天,維護就有可能會因不同的開發人員、不同的產品、不同的廠家而造成功能類似而接口不同的情況,此時就是適配器模式大展拳腳的時候了。

現在把教練給球員們分配任務的例子用適配器模式實現

球員類

  public abstract class Player {   protected String name;   public Player(String name) {   this.name = name;   }   //進攻和防守方法   public abstract void attack();   public abstract void defense();  }

 

後衛、中鋒、前鋒類

  //前鋒  public class Forwards extends Player {   public Forwards(String name) {   super(name);   }   @Override   public void attack() {   System.out.println("前鋒:"+name+"進攻");   }   @Override   public void defense() {   // TODO Auto-generated method stub   System.out.println("前鋒:"+name+"防守");   }  }  //中鋒  public class Center extends Player {   public Center(String name) {   super(name);   }   @Override   public void attack() {   System.out.println("中鋒:"+name+"進攻");   }     @Override   public void defense() {   // TODO Auto-generated method stub   System.out.println("中鋒:"+name+"防守");   }  }  //後衛  public class Guards extends Player {   public Guards(String name) {   super(name);   }   @Override   public void attack() {   System.out.println("後衛:"+name+"進攻");   }   @Override   public void defense() {   // TODO Auto-generated method stub   System.out.println("後衛:"+name+"防守");   }  }

 

測試方法

  public class Test {   public static void main(String[] args) {   Player peter = new Forwards("peter");   peter.attack();   Player mike = new Guards("mike");   mike.attack();      Player zhangsan = new Center("張三");   zhangsan.attack();   zhangsan.defense();   }  }

 

輸出結果:

前鋒:peter進攻
 後衛:mike進攻
 中鋒:張三進攻
 中鋒:張三防守

球員“張三”不會說英語,需要翻譯,用適配器模式完善代碼

  //外籍中鋒  public class ForeignCenter {   private String name;   //外籍中鋒只懂得中文“進攻”   public void jingong() {   System.out.println("中鋒:"+name+"進攻");   }   //外籍中鋒只懂得中文“防守”   public void fangshou() {   System.out.println("中鋒:"+name+"防守");   }     //省略getter、setter方法  }

 

  //翻譯者  public class Translator extends Player {   //聲明並實例化一個內部“外籍中鋒”對象,表面翻譯者與外籍球員有關聯   private ForeignCenter wjzf = new ForeignCenter();      public Translator(String name) {   super(name);   wjzf.setName(name);   }      @Override   public void attack() {   //翻譯者將attack翻譯為jingong 告訴外籍中鋒   wjzf.jingong();   }     @Override   public void defense() {   //翻譯者將defense翻譯為fangshou 告訴外籍中鋒   wjzf.fangshou();   }  }

 

main方法修改代碼如下:

  //翻譯者  public class Translator extends Player {   //聲明並實例化一個內部“外籍中鋒”對象,表面翻譯者與外籍球員有關聯   private ForeignCenter wjzf = new ForeignCenter();      public Translator(String name) {    super(name);    wjzf.setName(name);   }      @Override   public void attack() {    //翻譯者將attack翻譯為jingong 告訴外籍中鋒    wjzf.jingong();   }     @Override   public void defense() {    //翻譯者將defense翻譯為fangshou 告訴外籍中鋒    wjzf.fangshou();   }  }

 

現在就算是張三不懂英文,教練不懂中文,但因為有了翻譯者,團隊溝通合作成為了可能。

如果能事先預防接口不同的問題,不匹配問題就不會發生:在有小的接口不統一問題發生時,及時重構,問題不至於擴大:只有碰到無法改變原有設計和代碼的情況時,才考慮適配。

事後控制不如事中控制,事中控制不如事前控制。



[月球人 ] 實例講解JAVA 適配器模式已經有233次圍觀

http://coctec.com/docs/java/show-post-239775.html