|--什麼是裝飾模式。
裝飾模式:是你還是你,一切拜託你(借用老崔經典詞)。
它是由繼承出現的,先有繼承,再有裝飾。
回憶繼承
好處:提高複用性,讓可以重複使用,通過方法重寫利用後期擴展。
壞處:由於類與類之間的繼承關係,但他們關係增強,耦性也就高了。不符合java宗旨:低耦合,高內聚。
對比如下:
a: 有一個Witer體系
|--TxtWrite
|--Mp3Write
|--DIDWrite
上面是一個普通子類實現,調用者覺得執行太慢,要求對三者進行增強(高效|緩衝)。修改如下
class myBuffereWrite exetends Write{
//接收子類:Fu f = new Zi();
private Write ziWrite;
public BuffereWrite(Write ziWrite)
{
this.ziWrite = ziWrite;
}
public void writeLine(String line)
{
//使用ziWrite進行整容處理,然後一行數據保存到write中。
}
public void close()
{
ziWrite.clese();//多態(調用的還是子類)!
}
public void flash(){
ziWrite.flash();//多態(調用的還是子類)!
}
....//重寫Write的抽象方法,調用的myBuffereWrite中的,再方法裏邊調用是傳送ziWrite。只不過在調用它之前給它做了一些手術。
}
|--總結
1:比如你使用Write的高效功能,那你就創建myBuffereWrite,傳遞你的對其高效的對象,比如FileWrite();
2:裝飾模式體現了對一個對象(功能)的增強(高內聚),然後緊密性比較弱(低耦合)。
3:JDK中用的裝飾就挺多的,比如BufferedWriter(Writer out);PrintStream(OutputStream out);ObjectInputStream(InputStream in)等。
|--代碼示例
模擬BuffereReader裝飾類
package com.Decoration;
import java.io.IOException;
import java.io.Reader;
/**
* @author hubiao
* 模擬BuffereReader裝飾類
*
* 分析:模擬一個類,就是自定一個類,實現它的特有方法:ReadLine();
* 1:模擬什麼:特有方法
* 2:你有什麼:根據裝飾特點,自定的類繼承一個抽象類,因爲BuffereReader的readLine底層也是繼承Reader中的。
* 我們要做的,也是繼承Reader,寫一個與BuffereReader一樣的ReadLine方法來。
*/
public class MyBuffere extends Reader {
/*Reader是一個抽象類的父類,將需要高效的類都實現了它。都是它的子類。*/
private Reader reader = null;
public MyBuffere(Reader reader){
this.reader = reader;
}
public int read(char[] cbuf, int off, int len) throws IOException {
return reader.read(cbuf, off, len);
}
public String readLine() throws IOException
{
/**
* 1:這裏要思考,使用
* A:read(char[] cbuf, int off, int len);一次讀取一緩衝區
* B:read();//一次讀取一個字符串
* 2:分析
* 我們模擬readLine目的是爲了模擬什麼?還不是爲了實現BufferedReader中的readerLine一次讀取一行的高效方法。
* 然後使用A方法不合適,因爲它一次讀取一個char容量定義的長度,我們封裝好的代碼很難獲知調用者要讀取的數據文本的每行數據有多長。
* 使用B方法的好處,是一次讀取一個字符,當遇到\r\n就說明是一行的結束,則說一行讀取完畢,那怎麼一行的數據每個字符用什麼保存呢?
* 使用String, 這...太可怕了吧,因爲我們知道String在java中是一個常量池。一但賦值,將不可變。所以選擇效率高的StringBuilder
* 把每個字符拼接到StringBuffer中,再返回給調用者。
*/
//單字符容器
StringBuffer buffer = new StringBuffer();
//每個字符
int read = 0;
while((read = reader.read())!=-1)
{
char chr = (char) read;
if(chr=='\r')
continue;
if(chr=='\n')
return buffer.toString();
else
buffer.append(chr);
}
//防止讀取的是最後一行,則沒有\r\n,那麼再判斷緩衝區中是否有值?如果有,則再返回。
if(buffer.length() > 0 )
return buffer.toString();
else
return null;
}
public void close() throws IOException {
reader.close();
}
}
模擬LineNumberReader
/**
* @author hubiao
* 模擬LineNumberReader
* 也是同樣,模擬,就是自定一個類,模擬需求給出的特殊方法:獲取每個行號,然後讀取每一行。
*/
public class MyLineNumberReader extends Reader{
/*接收傳遞子類對象,Fu f = new Zi();//多態*/
private Reader reader;
private int lineNumber;//行號
public MyLineNumberReader(Reader reader) {
this.reader = reader;
}
public int read(char[] cbuf, int off, int len) throws IOException {
return reader.read(cbuf, off, len);
}
public String readLine() throws IOException
{
//單字符容器
StringBuffer buffer = new StringBuffer();
//每個字符
int read = 0;
while((read = reader.read())!=-1)//-1表示讀取到流的結尾!
{
char chr = (char) read;
if(chr=='\r')
continue;
if(chr=='\n'){
lineNumber++;
return buffer.toString();
}
else
buffer.append(chr);
}
//防止讀取的是最後一行,則沒有\r\n,那麼再判斷緩衝區中是否有值?如果有,則再返回。
if(buffer.length() > 0 ){
lineNumber++;
return buffer.toString();
}else
return null;
}
public void close() throws IOException {
reader.close();
}
public int getLineNumber() {
return lineNumber;
}
public void setLineNumber(int lineNumber) {
this.lineNumber = lineNumber;
}
}