最近我給女朋友買了一款可以更換外殼的手機,F在的外殼是紅色的,如果我想用這款手機的時候,會更換成銀灰色的外殼。但是我不能隨意更換天線或者話筒,因為這些功能模塊在手機生產的時候就已經被固定了。
軟件中的修飾者(decorator),和手機的外殼一樣,封裝了一些可以替換的功能。例如下面是一段替換Swing中表模型的代碼:
TableSortDecorator sortDecorator = new TableSortDecorator(table.getModel());
table.setModel(sortDecorator);
在這段代碼中,程序首先將表模型包裝在一個修飾對象中。以后當表對它的模型進行操作的時候,它實際上操作的是排序修飾對象(sortDecorator),該修飾對象在表模型中加入了排序功能,而將其他基本的功能委托給缺省的表模型,在修飾模型中,這個缺省的表模型又被稱為真實對象(real subject)。
在Java的編程中,基類和子類的繼承關系在編譯的時候就被固定了,就像手機的天線和話筒一樣。由于繼承關系是靜態的,開發人員無法在程序運行時改變對象的行為。但是通過修飾者開發人員可以在運行時拼裝對象,因此修飾模式提供了一種比繼承更靈活的功能擴充模式。
修飾模式(Decorator Pattern)
在運行時將特定的功能綁定在對象上,這就是修飾模式的核心。修飾模式比繼承更加靈活,因為后者是在編譯時就將特定的功能綁定到類上。
下面然我們來看一個簡單的I/O例子:
FileReader frdr = new FileReader(filename);
LineNumberReader lrdr = new LineNumberReader(frdr);
這段代碼中創建了一個Reader:lrdr。它從一個文件中讀取數據并跟蹤文件的行號。在第一行創建的frdr對象能夠從文件中讀取數據,而第二行給lrdr增加了跟蹤行號的功能。在運行時(runtime),修飾者將方法調用傳遞給它所修飾的真實對象。在上面的例子中,lrdr將方法調用傳遞給它修飾的真實對象frdr。修飾者除了能夠進行方法傳遞外,還能夠增加類的功能。例如在上面的例子中,lrdr能夠跟蹤當前的文件流讀入數據的行號。
而下面的例子顯示了如何在程序中使用修飾者lrdr。程序將數據按行從文件中讀出后,加上行號輸出到屏幕上。
try {
LineNumberReader lrdr = new LineNumberReader(new FileReader(filename));
for(String line; (line = lrdr.readLine()) != null;)rticle.txt {
System.out.print(lrdr.getLineNumber() + ":\t" + line);
}
}
catch(java.io.FileNotFoundException fnfx) {
fnfx.printStackTrace();
}
catch(java.io.IOException iox) {
iox.printStackTrace();
}
(未完待續)
文章來源于領測軟件測試網 http://www.kjueaiud.com/