CodeGym /Java Blog /Toto sisi /適配器設計模式
John Squirrels
等級 41
San Francisco

適配器設計模式

在 Toto sisi 群組發布
你好!今天我們將討論一個重要的新話題:設計模式。這些圖案是什麼?我想你一定知道“不要重新發明輪子”這句話。在編程中,與許多其他領域一樣,存在大量常見情況。隨著軟件開發的發展,已經為它們中的每一個創建了現成的解決方案。這些解決方案稱為設計模式。按照慣例,模式是這樣制定的一些解決方案:“如果您需要在程序中執行 X,那麼這是執行此操作的最佳方法”。有很多圖案。您絕對應該熟悉的優秀書籍《Head First Design Patterns》就是獻給他們的。 適配器設計模式 - 2簡而言之,一個模式由一個常見問題和一個相應的解決方案組成,可以被認為是一種標準。在今天的課程中,我們將遇到其中一種模式:適配器。顧名思義,您在現實生活中已經多次遇到適配器。一些最常見的適配器是許多計算機和筆記本電腦都有的讀卡器。 適配器設計模式 - 3假設我們有某種存儲卡。所以有什麼問題? 它不知道如何與計算機交互。它們不共享通用接口。 電腦有USB接口,但是我們不能把內存卡插進去。卡無法插入電腦,所以我們無法保存我們的照片、視頻和其他數據。讀卡器就是解決這個問題的適配器。畢竟,它有 USB 數據線!與卡本身不同,讀卡器可以插入計算機。它們與計算機共享一個通用接口:USB。讓我們看看這在實踐中是怎樣的:

public interface USB { 

   void connectWithUsbCable(); 
}
這是我們的 USB 接口,只有一種通過 USB 連接的方法。

public class MemoryCard { 

   public void insert() { 
       System.out.println("Memory card successfully inserted!"); 
   } 

   public void copyData() { 
       System.out.println("The data has been copied to the computer!"); 
   } 
}
這是我們代表存儲卡的類。它已經有了我們需要的 2 個方法,但問題來了:它沒有實現 USB 接口。卡無法插入 USB 端口。

public class CardReader implements USB { 

   private MemoryCard memoryCard; 

   public CardReader(MemoryCard memoryCard) { 
       this.memoryCard = memoryCard; 
   } 

   @Override 
   public void connectWithUsbCable() { 
       this.memoryCard.insert(); 
       this.memoryCard.copyData(); 
   } 
}
這是我們的適配器!什麼是CardReader類做什麼,究竟是什麼使它成為適配器?一切都很簡單。正在適配的類 (MemoryCard) 成為適配器的字段之一。這是有道理的。當我們在現實生活中將存儲卡放入讀卡器時,它也成為其中的一部分。與存儲卡不同,適配器與計算機共享一個接口。它有一根 USB 電纜,即它可以通過 USB 連接到其他設備。這就是我們的 CardReader 類實現 USB 接口的原因。但是這個方法內部究竟發生了什麼?正是我們需要發生的事情!適配器將工作委託給我們的存儲卡。實際上,適配器本身不執行任何操作。讀卡器沒有任何獨立的功能。它的工作只是連接電腦和記憶卡,讓記憶卡做它的工作——複製文件!connectWithUsbCable()方法)來滿足存儲卡的“需要”。讓我們創建一些客戶端程序來模擬一個想要從存儲卡複製數據的人:

public class Main { 

   public static void main(String[] args) { 

       USB cardReader = new CardReader(new MemoryCard()); 
       cardReader.connectWithUsbCable(); 
   } 
}
那麼我們得到了什麼?控制台輸出:

Memory card successfully inserted! 
The data has been copied to the computer!
出色的。我們達到了目的!下面是一個視頻鏈接,其中包含有關適配器模式的信息:

Reader 和 Writer 抽像類

現在我們將回到我們最喜歡的活動:了解幾個處理輸入和輸出的新類 :) 我想知道我們已經了解了多少。今天我們將討論類Reader 和Writer類。為什麼特別是那些類?因為它們與我們之前關於適配器的部分有關。讓我們更詳細地研究它們。我們將從 Reader. Reader是一個抽像類,所以我們不能顯式地創建對象。  但其實你已經很熟悉了!畢竟,您很熟悉 和BufferedReaderInputStreamReader,它們是它的後代 :)

public class BufferedReader extends Reader { 
… 
} 

public class InputStreamReader extends Reader { 
… 
}
該類InputStreamReader是一個經典的適配器。 您可能還記得,我們​​可以將一個對像傳遞InputStream給它的構造函數。為此,我們通常使用System.in變量:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
但是InputStreamReader做什麼呢? 與每個適配器一樣,它將一個接口轉換為另一個接口。  在這種情況下,InputStream接口到Reader接口。最初,我們有這個InputStream類。它運行良好,但您只能使用它來讀取單個字節。此外,我們還有一個Reader抽像類。它有一些非常有用的功能——它知道如何閱讀字符!我們當然需要這種能力。但在這裡,我們面臨通常由適配器解決的經典問題——不兼容的接口。這意味著什麼?讓我們看一下 Oracle 文檔。下面是類的方法InputStream適配器設計模式 - 4一組方法就是接口。正如你所看到的,這個類有一個read()方法(實際上有幾個變體),但它只能讀取字節:單個字節或使用緩衝區的幾個字節。但是這個選項不適合我們——我們想要讀取字符。我們需要已經在Reader抽像類中實現的功能。我們也可以在文檔中看到這一點。 適配器設計模式 - 5但是,InputStream和 Reader接口不兼容!如您所見,該read()方法的每個實現都有不同的參數和返回值。這就是我們需要的地方InputStreamReader!它將充當我們類之間的適配器。 與我們上面考慮的讀卡器示例一樣,我們將被適配類的一個實例放在適配器類“內部”,即我們將一個實例傳遞給它的構造函數。在前面的例子中,我們MemoryCard在裡面放了一個對象CardReader。現在我們將一個InputStream 對像傳遞給InputStreamReader構造函數!我們使用我們熟悉的System.in變量作為InputStream

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
事實上,查看 的文檔InputStreamReader,我們可以看到改編成功了 :) 現在我們有了讀取字符的方法供我們使用。 適配器設計模式 - 6儘管我們的System.in對象(綁定到鍵盤的流)最初不允許這樣做,但該語言的創建者通過實施適配器模式解決了這個問題。Reader與大多數 I/O 類一樣,抽像類有一個孿生兄弟 — Writer. 它有同樣大的優勢 Reader ——它提供了一個方便的界面來處理角色。對於輸出流,問題及其解決方案看起來與輸入流相同。有一個OutputStream只能寫字節的類,有一個Writer知道如何處理字符的抽像類,並且有兩個不兼容的接口。這個問題又一次被適配器模式解決了。我們使用類來輕鬆地使 和 類OutputStreamWriter的兩個接口 相互適配。將字節流傳遞給構造函數後,我們可以使用 an來寫入字符而不是字節! WriterOutputStreamOutputStreamOutputStreamWriter

import java.io.*; 

public class Main { 

   public static void main(String[] args) throws IOException { 

       OutputStreamWriter streamWriter = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt")); 
       streamWriter.write(32144); 
       streamWriter.close();
   } 
}
我們將代碼為 32144 (綐) 的字符寫入我們的文件,從而無需使用字節 :) 今天就到此為止。下節課見!:)
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION