設計模式在JDK中的運用
今天覆習了一下設計模式,也從原始碼中去尋找了一下設計模式在JDK中的運用。
介面卡模式:
核心思想就是將一個介面適配(偽裝成)到另一個介面。在Java I/O中運用到了很多介面卡模式,例如將字串資料轉變成位元組資料儲存到檔案中或將位元組資料轉變成流資料等,下面用InputStreamReader 舉例。
public class InputStreamReader extends Reader {//介面卡類InputStreamReader繼承於目標介面類 private final StreamDecoder sd;//用JVM轉碼的過程,用於將位元組轉為字元 /** * Creates an InputStreamReader that uses the default charset. * * @param in An InputStream */ public InputStreamReader(InputStream in) {//可以看到構造引數是InputStream,這就是介面卡的核心 super(in); try { sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object } catch (UnsupportedEncodingException e) { // The default encoding should always be available throw new Error(e); } } }
從上面可以看出,介面卡類InputStramReader 繼承於目標抽象類Reader,在下面的構造引數中可以看到是怎麼將源抽象類InputStram 轉換成 Reader需要的位元組的,用的是streamDecoder。 這樣看來大體結構就已經很清晰了:
InputStramReader是介面卡類,用於將InputStram 字元流轉換成 Reader需要的位元組流。
Reader:目標抽象類,即為需要轉換的目標。
InputStram:源目標抽象類,即需要被轉換的目標。
工廠模式:定義一個用於建立物件的介面,讓子類決定例項化哪一個類,工廠方法使一個類的例項化延遲到其子類。
例如在 java.util.Calendar 中的getInstance()方法就使用了簡單工廠模式。
private static Calendar createCalendar(TimeZone zone, Locale aLocale) { CalendarProvider provider = LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale) .getCalendarProvider(); if (provider != null) { try {//LocaleProviderAdapter.getAdapter中的反射機制得到aLocale然後根據aLocale 返回不同的物件 return provider.getInstance(zone, aLocale); } catch (IllegalArgumentException iae) { // fall back to the default instantiation } } Calendar cal = null; if (aLocale.hasExtensions()) {//和上面思想一致 String caltype = aLocale.getUnicodeLocaleType("ca"); if (caltype != null) { switch (caltype) { case "buddhist": cal = new BuddhistCalendar(zone, aLocale); break; case "japanese": cal = new JapaneseImperialCalendar(zone, aLocale); break; case "gregory": cal = new GregorianCalendar(zone, aLocale); break; } } }
上面原始碼中可以看出LocaleProviderAdapter.getAdapter中使用反射機制得到aLocale然後根據aLocale 返回不同的物件。是一個標準的工廠模式使用。
裝飾者模式:動態地給一個物件新增一些額外的功能。
裝飾者模式可以動態的給類提供額外的功能,通常又一個裝飾類,裝飾實現類,然後抽象裝飾類繼承於需要被裝飾的類。
例如在繼承於InputStream的FilterInputStream就是裝飾類,而DataInputStream,BufferedInputStream,PushBackInputStream都繼承於裝飾類 FilterInputStream,作為裝飾實現類; 為被裝飾的類InputStream提供額外的功能。例如BufferedInputStream 就提供了快取功能。下面是虛擬碼:
public class FilterInputStream extends InputStream {}//裝飾類
public class BufferedInputStream extends FilterInputStream {}//裝飾實現類
//具體實現忽略
吃午飯去了,下次繼續更新。。