Java設計模式之適配器模式(Adapter)


轉載:《JAVA與模式》之適配器模式

      這個總結的挺好的,為了加深印象,我自己再嘗試總結一下

1.定義:

     適配器模式把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。

     (太官方了,不太好理解

       其實就是要用到兩個不相關的類/接口,但是又沒有源代碼,或者不想修改源代碼,而增加一個類來完成合並使用的目的)

 

2.實現這個目的有兩個方法,繼承或者組合

   2.1.使用繼承(就是所謂的類適配器模式)

   2.2.使用組合(所謂的對象適配器模式)


       案例: 公司招員工,要求會講中、英、法、日四國語言,同時還很會編程的員工。

           招聘要求類 JobNeedSkill 接口:

1 package design.pattern.adapter2;
2 
3 public interface JobNeedSkill {
4     void speakChinese();
5     void speakEnglish();
6     void speakJapanese();
7     void speakFrench();
8     void goodCoding();
9 }
View Code

           而這里有個工人,技術超一流,可惜只會說中文

           Worker類:    

 1 package design.pattern.adapter2;
 2 
 3 public class Worker {
 4     public void goodCoding(){
 5         System.out.println("我編程也挺牛的哦");
 6     }
 7     
 8     public void speakChinese(){
 9         System.out.println("我只會說中文呢,能不能請我啊");
10     }
11 }
View Code

           招聘測試類 Test

 1 package design.pattern.adapter2;
 2 
 3 public class Test {
 4     //招聘員工
 5     public static void hireWorker(JobNeedSkill worker){
 6         System.out .println("恭喜你,你被錄用了,展示一下你的技能吧");
 7         
 8         System.out .println("===============================");
 9         worker.speakChinese();
10         worker.speakEnglish();
11         worker.speakFrench();
12         worker.speakJapanese();
13         worker.goodCoding();
14     }
15     
16     public static void main(String[] args){
17         //我是個只會說中文的工人 ,但我編程好 
18         Worker me = new Worker();
19         
20         //我們需要一個會說四國語言的員工
21 //        hireWorker(me);//直接招聘是不行了,再給他配個步步高點讀機吧
22         
23         /*
24          * 以上代碼為初始狀態,后面的代碼是后面根據需求增加的
25          * */
26         
27         //有步步高點讀機,這是使用了繼承的方式,類的適配模式
28         TheManHasBuBuGao bbg = new TheManHasBuBuGao();
29         hireWorker(bbg);
30         
31         System.out.println("*****************\r\n");
32         //這個自帶助理的,是使用了組合的方式,是對象的適配模式
33         WorkerHasAssistant gfs = new WorkerHasAssistant(me);
34         hireWorker(gfs);
35     }
36     
37 }
View Code

      很明顯,一開始的時候發現,盡管這個人技術很牛,但是只會說中文這一點,實在讓人覺得可惜,

      別說我們公司不能招聘了,就連eclipse都提示錯誤了:

         

            不過他的技術的確非常符合我們公司的需要,怎么辦呢,咋取舍呢······

            如果,如果他有一台 “步步高點讀機呢”

            TheManHasBuBuGao類:

 1 package design.pattern.adapter2;
 2 //這里使用了繼承的方式
 3 public class TheManHasBuBuGao extends Worker implements JobNeedSkill{
 4 
 5     @Override
 6     public void speakJapanese() {
 7         System.out.println("媽媽再也不用擔心我的日語了");
 8     }
 9 
10     @Override
11     public void speakFrench() {
12         System.out.println("哪里不會就點哪里,這樣法語也隨便搞定了");
13     }
14 
15     @Override
16     public void speakEnglish() {
17         System.out.println("So Easy.");
18     }
19 
20 }
View Code

         這樣問題就解決了,步步高點讀機就是好!

         不過他說他沒有步步高點讀機,但是他有一個貼身翻譯助理

         WorkerHasAssistant類:

 1 package design.pattern.adapter2;
 2 
 3 public class WorkerHasAssistant implements JobNeedSkill{
 4     //這個人有自己的助理翻譯,這里是使用了組合的方式
 5     private Worker worker;
 6     
 7     //在構造方法中傳進來
 8     public WorkerHasAssistant(Worker worker){
 9         this.worker = worker;
10     }
11 
12     @Override
13     public void goodCoding() {
14         worker.goodCoding();
15     }
16     @Override
17     public void speakChinese() {
18         //worker會說,直接用worker
19         worker.speakChinese();
20     }
21 
22     @Override
23     public void speakEnglish() {
24         //英語他不會說,這就要助手出馬翻譯了
25         System.out.println("我是他的翻譯,他說 Hello World.");
26     }
27 
28     @Override
29     public void speakJapanese() {
30         //日語他也不會說,這還是要助手出馬翻譯了
31         System.out.println("八嘎");
32     }
33 
34     @Override
35     public void speakFrench() {
36         //每錯,他英語也不行
37         System.out.println("He can say English too.");
38     }
39 
40 
41 }
View Code

         最后運行的效果是:

         

 

    把文章看完是個好習慣,

    在最后還要特別說明一下,適配器模式還有一種默認缺省的用法,這個目的跟上面的略微不同,但做法是一致的,

    都是增加了一個適配類,哈哈(別跟別的設計模式搞混了哦,同時這種用法在Swing開發里經常用到)

    Skill 接口:

1 package design.pattern.adapter2;
2 
3 public interface Skill {
4     void sing();
5     void dance();
6     void fly();
7     void cry();
8     //.......一大堆方法
9 }
View Code

如果 Person類直接實現 Skill接口,就會變成這樣:

 1 package design.pattern.adapter2;
 2 
 3 public class Person implements Skill{
 4 
 5     @Override
 6     public void sing() {
 7         // TODO Auto-generated method stub
 8         
 9     }
10 
11     @Override
12     public void dance() {
13         // TODO Auto-generated method stub
14         
15     }
16 
17     @Override
18     public void fly() {
19         // TODO Auto-generated method stub
20         
21     }
22 
23     @Override
24     public void cry() {
25         // TODO Auto-generated method stub
26         
27     }
28 
29 }
View Code

必須同時實現Skill接口中的所有方法,但其實我們關注的只是其中某一個方法而已,

所以,這時候就可以增加一個中間類SkillAdapter,這個類也實現了Skill接口,並實現了所有方法,不過是空實現:

 1 package design.pattern.adapter2;
 2 
 3 public class SkillAdapter implements Skill{
 4 
 5     @Override
 6     public void sing() {
 7         // TODO Auto-generated method stub
 8         
 9     }
10 
11     @Override
12     public void dance() {
13         // TODO Auto-generated method stub
14         
15     }
16 
17     @Override
18     public void fly() {
19         // TODO Auto-generated method stub
20         
21     }
22 
23     @Override
24     public void cry() {
25         // TODO Auto-generated method stub
26         
27     }
28 
29 }
View Code

而我們在繼承這個中間類(Adapter),再重寫我們所關注的方法就可以了,而無需做過多無謂的操作:

1 package design.pattern.adapter2;
2 
3 public class NewPerson extends SkillAdapter{
4     public void sing(){
5         System.out.println("我只會唱歌,別的我都不會了");
6     }
7 }
View Code

最后再總結一下:

     因此如果不是很有必要,可以不使用適配器,而是直接對系統進行重構(也就是去改代碼),

     除了這種默認缺省的適配器外,前面的例子都是在沒辦法情況下的辦法而已。

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM