Java--23种设计模式之decorator模式
裝飾模式:裝飾模式以對(duì)客戶(hù)端透明的方式擴(kuò)展對(duì)象的功能,是繼承關(guān)系的一個(gè)替代方案,提供比繼承更多的靈活性。動(dòng)態(tài)給一個(gè)對(duì)象增加功能,這些功能可以再動(dòng)態(tài)的撤消。增加由一些基本功能的排列組合而產(chǎn)生的非常大量的功能。是在不必改變?cè)?lèi)文件和不使用繼承的情況下,動(dòng)態(tài)的擴(kuò)展一個(gè)對(duì)象的功能。它是通過(guò)創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來(lái)包裹真實(shí)的對(duì)象
趣味解釋:DECORATOR—Mary過(guò)完輪到Sarly過(guò)生日,還是不要叫她自己挑了,不然這個(gè)月伙食費(fèi)肯定玩完,拿出我去年在華山頂上照的照片,在背面寫(xiě)上“最好的的禮物,就是愛(ài)你的Fita”,再到街上禮品店買(mǎi)了個(gè)像框(賣(mài)禮品的MM也很漂亮哦),再找隔壁搞美術(shù)設(shè)計(jì)的Mike設(shè)計(jì)了一個(gè)漂亮的盒子裝起來(lái)……,我們都是Decorator,最終都在修飾我這個(gè)人呀,怎么樣,看懂了嗎?趣味解釋參見(jiàn):http://blog.jobbole.com/20496/
Java代碼中實(shí)現(xiàn):以Java中的輸入輸出流為例,Java中的處理流即是對(duì)節(jié)點(diǎn)流的包裝和裝飾
package decorator;import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.PushbackInputStream; import java.io.PushbackReader;public class IOTest {/* test.txt內(nèi)容:* hello world!*/public static void main(String[] args) throws IOException, ClassNotFoundException {//文件路徑可自行更換final String filePath = "F:/eclipse/workspace/decorator/Test.txt";//InputStream相當(dāng)于被裝飾的接口或者抽象類(lèi),FileInputStream相當(dāng)于原始的待裝飾的對(duì)象,FileInputStream無(wú)法裝飾InputStream//另外FileInputStream是以只讀方式打開(kāi)了一個(gè)文件,并打開(kāi)了一個(gè)文件的句柄存放在FileDescriptor對(duì)象的handle屬性//所以下面有關(guān)回退和重新標(biāo)記等操作,都是在堆中建立緩沖區(qū)所造成的假象,并不是真正的文件流在回退或者重新標(biāo)記InputStream inputStream = new FileInputStream(filePath);final int len = inputStream.available();//記錄一下流的長(zhǎng)度System.out.println("FileInputStream不支持mark和reset:" + inputStream.markSupported());System.out.println("---------------------------------------------------------------------------------");/* 下面分別展示三種裝飾器的作用BufferedInputStream,DataInputStream,PushbackInputStream,LZ下面做了三個(gè)裝飾器的功能演示 *///首先裝飾成BufferedInputStream,它提供我們mark,reset的功能BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);//裝飾成 BufferedInputStreamSystem.out.println("BufferedInputStream支持mark和reset:" + bufferedInputStream.markSupported());bufferedInputStream.mark(0);//標(biāo)記一下char c = (char) bufferedInputStream.read();System.out.println("Test.txt文件的第一個(gè)字符:" + c);bufferedInputStream.reset();//重置c = (char) bufferedInputStream.read();//再讀System.out.println("重置以后再讀一個(gè)字符,依然會(huì)是第一個(gè)字符:" + c);bufferedInputStream.reset();System.out.println("---------------------------------------------------------------------------------");//裝飾成 DataInputStream,我們?yōu)榱擞质褂肈ataInputStream,又使用BufferedInputStream的mark reset功能,所以我們?cè)龠M(jìn)行一層包裝//注意,這里如果不使用BufferedInputStream,而使用原始的InputStream,read方法返回的結(jié)果會(huì)是-1,即已經(jīng)讀取結(jié)束//因?yàn)锽ufferedInputStream已經(jīng)將文本的內(nèi)容讀取完畢,并緩沖到堆上,默認(rèn)的初始緩沖區(qū)大小是8192BDataInputStream dataInputStream = new DataInputStream(bufferedInputStream);dataInputStream.reset();//這是BufferedInputStream提供的功能,如果不在這個(gè)基礎(chǔ)上包裝會(huì)出錯(cuò)System.out.println("DataInputStream現(xiàn)在具有readInt,readChar,readUTF等功能");int value = dataInputStream.readInt();//讀出來(lái)一個(gè)int,包含四個(gè)字節(jié)//我們轉(zhuǎn)換成字符依次顯示出來(lái),可以看到LZ文件的前四個(gè)字符String binary = Integer.toBinaryString(value);int first = binary.length() % 8;System.out.print("使用readInt讀取的前四個(gè)字符:");for (int i = 0; i < 4; i++) {if (i == 0) {System.out.print(((char)Integer.valueOf(binary.substring(0, first), 2).intValue()));}else {System.out.print(((char)Integer.valueOf(binary.substring(( i - 1 ) * 8 + first, i * 8 + first), 2).intValue()));}}System.out.println();System.out.println("---------------------------------------------------------------------------------");//PushbackInputStream無(wú)法包裝BufferedInputStream支持mark reset,因?yàn)樗采w了reset和mark方法//因?yàn)榱饕呀?jīng)被讀取到末尾,所以我們必須重新打開(kāi)一個(gè)文件的句柄,即FileInputStreaminputStream = new FileInputStream(filePath);PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream,len);//裝飾成 PushbackInputStreamSystem.out.println("PushbackInputStream裝飾以后支持退回操作unread");byte[] bytes = new byte[len];pushbackInputStream.read(bytes);//讀完了整個(gè)流System.out.println("unread回退前的內(nèi)容:" + new String(bytes));pushbackInputStream.unread(bytes);//再退回去bytes = new byte[len];//清空byte數(shù)組pushbackInputStream.read(bytes);//再讀System.out.println("unread回退后的內(nèi)容:" + new String(bytes));System.out.println("---------------------------------------------------------------------------------");/* 以上有兩個(gè)一層裝飾和一個(gè)兩層裝飾,下面我們先裝飾成Reader,再進(jìn)行其它裝飾 *///由于之前被PushbackInputStream將流讀取到末尾,我們需要再次重新打開(kāi)文件句柄inputStream = new FileInputStream(filePath);InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"utf-8");//先裝飾成InputStreamReaderSystem.out.println("InputStreamReader有reader的功能,比如轉(zhuǎn)碼:" + inputStreamReader.getEncoding());System.out.println("---------------------------------------------------------------------------------");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);//我們進(jìn)一步在reader的基礎(chǔ)上裝飾成BufferedReaderSystem.out.println("BufferedReader有readLine等功能:" + bufferedReader.readLine());System.out.println("---------------------------------------------------------------------------------");LineNumberReader lineNumberReader = new LineNumberReader(inputStreamReader);//我們進(jìn)一步在reader的基礎(chǔ)上裝飾成LineNumberReaderSystem.out.println("LineNumberReader有設(shè)置行號(hào),獲取行號(hào)等功能(行號(hào)從0開(kāi)始),當(dāng)前行號(hào):" + lineNumberReader.getLineNumber());System.out.println("---------------------------------------------------------------------------------");//此處由于剛才被readLine方法將流讀取到末尾,所以我們?cè)俅沃匦麓蜷_(kāi)文件句柄,并需要將inputstream再次包裝成readerinputStreamReader = new InputStreamReader(new FileInputStream(filePath));PushbackReader pushbackReader = new PushbackReader(inputStreamReader,len);//我們進(jìn)一步在reader的基礎(chǔ)上裝飾成PushbackReaderSystem.out.println("PushbackReader是擁有退回操作的reader對(duì)象");char[] chars = new char[len];pushbackReader.read(chars);System.out.println("unread回退前的內(nèi)容:" + new String(chars));pushbackReader.unread(chars);//再退回去chars = new char[len];//清空char數(shù)組pushbackReader.read(chars);//再讀System.out.println("unread回退后的內(nèi)容:" + new String(chars));}}運(yùn)行結(jié)果:
FileInputStream不支持mark和reset:false
---------------------------------------------------------------------------------
BufferedInputStream支持mark和reset:true
Test.txt文件的第一個(gè)字符:H
重置以后再讀一個(gè)字符,依然會(huì)是第一個(gè)字符:H
---------------------------------------------------------------------------------
DataInputStream現(xiàn)在具有readInt,readChar,readUTF等功能
使用readInt讀取的前四個(gè)字符:Hell
---------------------------------------------------------------------------------
PushbackInputStream裝飾以后支持退回操作unread
unread回退前的內(nèi)容:Hello World!
unread回退后的內(nèi)容:Hello World!
---------------------------------------------------------------------------------
InputStreamReader有reader的功能,比如轉(zhuǎn)碼:UTF8
---------------------------------------------------------------------------------
BufferedReader有readLine等功能:Hello World??
---------------------------------------------------------------------------------
LineNumberReader有設(shè)置行號(hào),獲取行號(hào)等功能(行號(hào)從0開(kāi)始),當(dāng)前行號(hào):0
---------------------------------------------------------------------------------
PushbackReader是擁有退回操作的reader對(duì)象
unread回退前的內(nèi)容:Hello World!
?上圖中畫(huà)出了輸入輸出流的類(lèi)圖,和裝飾器模式對(duì)照。其中InputStreamReader轉(zhuǎn)換流比較特殊,即是InputStream輸入流裝飾產(chǎn)生,同時(shí)又是Reader字符流的裝飾原始類(lèi)。
分析此圖可以看出:裝飾器模式的靈活,我們創(chuàng)建的一個(gè)FileInputstream對(duì)象,我們可以使用各種裝飾器讓它具有不同的特別的功能,這正是動(dòng)態(tài)擴(kuò)展一個(gè)類(lèi)的功能的最佳體現(xiàn),而裝飾器模式的靈活性正是JAVA中IO所需要的,不得不贊一下JAVA類(lèi)庫(kù)的建造者實(shí)在是強(qiáng)悍。上述的XXXXInputStream的各個(gè)類(lèi)都繼承了InputStream,這樣做不僅是為了復(fù)用InputStream的父類(lèi)功能(InputStream也是一種模板方法模式,它定義了read(byte[])方法的簡(jiǎn)單算法,并將read()方法交給具體的InputStream去實(shí)現(xiàn)),也是為了可以重疊裝飾,即裝飾器也可以再次被裝飾,而過(guò)渡到Reader以后,Reader的裝飾器體系則是類(lèi)似的。
總結(jié):裝飾器模式就是一個(gè)可以非常靈活的動(dòng)態(tài)擴(kuò)展類(lèi)功能的設(shè)計(jì)模式,它采用組合的方式取代繼承,使得各個(gè)功能的擴(kuò)展更加獨(dú)立和靈活。
參考文章:http://www.cnblogs.com/zuoxiaolong/p/pattern11.html
轉(zhuǎn)載于:https://www.cnblogs.com/graceting/p/4120210.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的Java--23种设计模式之decorator模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 网站自行备案流程
- 下一篇: C# random helper cla