看板 java 關於我們 聯絡資訊
剛好 First Head Design Pattern 的 ch3 有試閱 :D http://oreilly.com/catalog/hfdesignpat/chapter/ch03.pdf Java I/O 正是 real world decorator pattern 的例子。 decorator pattern 常被抱怨因為子類別太多難以看懂, 不過這件事通常要靠學習 decorator pattern 來解決。 請看第 24 頁(或頁碼101), decorator pattern 有 4 類基本的角色 1. 抽象的元件,用來定義基本行為 2. 實體元件,能直接使用的元件。 3. 抽象的裝飾者,定義裝飾者基本行為 4. 實體裝傭者,實作裝飾者行為。 InputStream 就是 [1] 抽象元件。 它定義所有 InputStream 衍生類別應用的共通行為。 而 FileInputStream、StringBufferInputStream、ByteArrayInputStream 等 都是能直接使用的元件[2]。 所謂「能直接」使用的意義是: 1. 它是最初的元件狀態來源, FileInputStream 的 Input 需來自 File 建構子需為 File 物件或 FileDescriptor 或檔案路徑 StringBufferInputStream 的 Input 需來自 String 建構子只能是字串 ByteArrayInputStream 的 Input 需來自 byte[] 建構子需為 byte[] 或 byte[] 區段 2. 它的實作不能透過裝飾而來,因為沒有狀態的本體,裝飾沒有意義。 先掌握非裝飾用的元件,再來看裝飾者的基本行為: http://java.sun.com/j2se/1.4.2/docs/api/java/io/FilterInputStream.html 它有唯一的建構子 InputStream。 這說明它的風格是透過建構的過程,實現裝飾的效果。 因此,下面這樣的用法是相當常見的: new LineNumberInputStream( new BufferedInputStream( new FileInputStream("foo.txt") ) ); FileInputStream 是實體元件負責提供狀態的來源, BufferedInputStream 裝飾 FileInputStream 提供讀檔時的 buffer 因為 read() 方法只會讀出適當的筆數,這樣做沒什麼效率。 透過 BufferedInputStream 預先讀出一「塊」資料,放在 buffer 內 read() 不會頻繁地讀寫硬碟,而是在 buffer 內的資料沒有時, 才會有實際的讀取作用。 LineNumberInputStream 提供行號的管理, 我想應該就是在 read() 要吐出資料前判斷是否有經過換行字元吧。 當我們認識 decorator pattern 並理解 Java IO 是這樣設計。 那麼面對再多的 subclass 就無需畏懼了。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.231.55.86