天天看點

深入了解擴充卡模式(類擴充卡、對象擴充卡、接口擴充卡)擴充卡模式

擴充卡模式

文章目錄

  • 擴充卡模式
    • 一、概述
    • 二、定義和結構
      • 1. 定義
      • 2. 結構
    • 三、類擴充卡模式
    • 四、對象擴充卡模式
    • 五、接口擴充卡模式
    • 六、适用場景

一、概述

如果去歐洲國家去旅遊的話,他們的插座如下圖最左邊,是歐洲标準。而我們使用的插頭如下圖最右邊所示,是以我們的筆記本電腦、手機在當地不能直接充電。是以就需要一個插座轉換器,轉換器第1面插入當地的插座,第2面供我們充電,這樣使得我們的插頭在當地能使用。這就是擴充卡模式的思想。

深入了解擴充卡模式(類擴充卡、對象擴充卡、接口擴充卡)擴充卡模式

二、定義和結構

1. 定義

  • 擴充卡模式是指将一個類的接口轉換成另外一個接口,使得原本由于接口不相容而不能一起工作的那些類能一起工作
  • 擴充卡模式分為類擴充卡模式和對象擴充卡模式
    • 類擴充卡模式的耦合度比較高,應用較少

2. 結構

擴充卡模式(Adapter)包含以下主要角色:

  • 目标接口:目前系統業務所期待的接口(想要轉換為的接口),它可以是抽象類或接口,比如上圖的最左邊
  • 适配者類:它是被通路和适配的元件接口,比如上圖的最右邊
  • 擴充卡類:它是一個轉換器,通過繼承或引用适配者的對象,把适配者接口轉換成目标接口,讓客戶按目标接口的格式通路适配者,比如上圖的中間位置

三、類擴充卡模式

實作方式:定義一個擴充卡類實作目标接口,同時又繼承适配者類

例:

現有一台電腦隻能讀取SD卡,而要讀取TF卡中的内容的話就需要使用到擴充卡模式,建立一個讀卡器(擴充卡),将TF卡中的内容讀取出來,對應的UML類圖如下所示:

深入了解擴充卡模式(類擴充卡、對象擴充卡、接口擴充卡)擴充卡模式

代碼實作:

  • SD卡接口(目标接口)
    public interface SDCard {
    
        //從SD卡中讀取資料
        String readSD();
    }
               
  • SD卡實作類(目标類)
    public class SDCardImpl implements SDCard {
    
        @Override
        public String readSD() {
            String msg = "SDCard read msg : hello word SD";
            return msg;
        }
    }
               
  • Computer類
    public class Computer {
    
        //隻能從SD卡中讀取資料
        public String readSD(SDCard sdCard) {
            if(sdCard == null) {
                throw  new NullPointerException("sd card is not null");
            }
            return sdCard.readSD();
        }
    }
               
  • TF卡接口(适配者接口)
    public interface TFCard {
    
        //從TF卡中讀取資料
        String readTF();
    }
               
  • TF卡實作類(适配者類)
    public class TFCardImpl implements TFCard {
    
        @Override
        public String readTF() {
            String msg = "TFCard read msg : hello word TFcard";
            return msg;
        }
    }
               
  • 擴充卡類(實作目标接口,繼承适配者類)
    public class SDAdapterTF extends TFCardImpl implements SDCard {
    
        //要按照目标接口的方法通路,是以重寫目标類的方法
        @Override
        public String readSD() {
            System.out.println("adapter read tf card");
            return readTF(); //通路适配者,通過繼承擁有此方法
        }
    }
               
  • 進行測試
    public class Client {
        public static void main(String[] args) {
            //建立計算機對象
            Computer computer = new Computer();
            //讀取SD卡中的資料
            String msg = computer.readSD(new SDCardImpl());
            System.out.println(msg);
            //SDCard read msg : hello word SD
    
            //使用該電腦讀取TF卡中的資料
            //定義擴充卡類,通過擴充卡類按照目标接口的格式通路适配者
            String msg1 = computer.readSD(new SDAdapterTF());
            System.out.println(msg1);
            //adapter read tf card
            //TFCard read msg : hello word TFcard
        }
    }
               
  • 類擴充卡的缺點
    • 違背了合成複用原則
      • 盡量先使用組合或者聚合等關聯關系來實作,其次才考慮使用繼承關系來實作
    • 目标類有接口規範時才可以使用
      • 由于類的單繼承性,擴充卡類無法繼承兩個類(隻能一個接口一個類)

四、對象擴充卡模式

實作方式:定義一個擴充卡類實作目标接口,适配者作為擴充卡類的屬性(使用組合或者聚合關系,類擴充卡模式采用的是繼承關系)

繼續對讀卡器案例進行改進,對應的UML類圖如下所示:

深入了解擴充卡模式(類擴充卡、對象擴充卡、接口擴充卡)擴充卡模式

代碼實作:

  • 隻需要修改擴充卡類的代碼即可(實作目标接口)
    public class SDAdapterTF implements SDCard {
    
        //适配者作為屬性出現,不再使用繼承關系
        private TFCard tfCard;
    
        //構造器
        public SDAdapterTF(TFCard tfCard) {
            this.tfCard = tfCard;
        }
    
        //重寫目标接口的方法,按照目标接口的格式通路
        @Override
        public String readSD() {
            System.out.println("adapter read tf card");
            return tfCard.readTF();
        }
    }
               
  • 進行測試
    public class Client {    
    	public static void main(String[] args) {        
    	//建立計算機對象       
    	Computer computer = new Computer();        
    	
    	//通過擴充卡類通路适配者,構造器中定義适配者        
    	SDAdapterTF sdAdapterTF = new SDAdapterTF(new TFCardImpl());        
    	String msg1 = computer.readSD(sdAdapterTF);        
    	System.out.println(msg1);        
    	//adapter read tf card        
    	//TFCard read msg : hello word TFcard    
    	}
    }
               
  • 優點
    • 遵循合成複用原則,解決了類擴充卡模式存在的問題

五、接口擴充卡模式

使用場景:當不希望實作一個接口中所有的方法時,可以建立一個抽象類Adapter ,實作此接口中的所有方法,并為該接口中的每個方法提供一個預設實作(空方法,使其不再成為抽象方法),那麼該抽象類的子類可以有選擇的覆寫抽象父類的某些方法來實作需求,而不必重寫所有方法

六、适用場景

  • 以前開發的系統存在滿足新系統功能需求的類,但其接口同新系統的接口不一緻
  • 使用第三方提供的元件,但元件接口定義和自己要求的接口定義不同