裝飾設計模式:基於已經存在的功能,提供增強的功能
裝飾設計模式的由來:
Reader
----TextReader
----MediaReader
要爲子類提供緩衝讀的功能
Reader
----TextReader
----BufferedTextReader
----MediaReader
-----BufferedMediaReader
Reader
----TextReader
----BufferedTextReader
----MediaReader
-----BufferedMediaReader
----OtherReader
-----BufferedOtherReader
既然都是提供緩衝讀的功能,那麼就可以把這個功能提取出來,單獨定義成一個類
誰需要被提高效率,就把誰作爲參數傳遞給這個類的構造方法
class BufferedReader
{
privateReader r;
publicBufferedReader(Reader r)
{
this.r = r;
}
}
這個體系就成了下邊的樣子:
Reader
----TextReader
----MediaReader
----OtherReader
----BufferedReader
裝飾設計模式的特點:
1:因爲是基於已有的功能提供增強的功能,所以還屬於原體系
2:是一個體系簡單化了
例子說明:
import java.io.*;
//實現LineNumberReader
class MyBufferedReader //extends Reader
{
private Reader r;//真正用來讀取文件的
private char[] arr = new char[1024];//相當於緩衝區
private int index;//數組使用的下標
private int count;//存儲字符個數的變量
public MyBufferedReader(Reader r)
{
this.r = r;
}
//實現一次讀一個字符的功能
public int myRead()throws IOException
{
//如果緩衝區中沒有數據,從文件中讀取數據到緩衝區
if(count==0)
{
count = r.read(arr);//從文件中讀取數據到緩衝區,返回的是讀取的字符的個數
index = 0;//下標重置爲0,從文件中讀了一批數據,從下標0開始取
}
if(count<0)
return -1;
//從緩衝區中取一個字符
int num = arr[index];
//下標加1
index++;
//數量減1
count--;
return num;
}
//實現一次讀一行的功能
//反覆調用myRead(),不夠一行的時候存儲,夠一行的時候返回
public String myReadLine()throws IOException
{
//使用StringBuilder實現存儲
StringBuilder sb = new StringBuilder();
int ch;
while((ch=myRead())!=-1)
{
if(ch=='\r')
continue;
else if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
return null;
}
public void myClose()throws IOException
{
r.close();
}
}
class MyLineNumberReader extends MyBufferedReader
{
private int lineNumber;
public MyLineNumberReader(Reader r)
{
super(r);
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
public int getLineNumber()
{
return this.lineNumber;
}
public String myReadLine()throws IOException
{
++lineNumber;
return super.myReadLine();
}
}
class Demo7
{
public static void main(String[] args)throws IOException
{
FileReader fr = new FileReader("Demo5.java");
//是一個裝飾類
MyLineNumberReader lnr = new MyLineNumberReader(fr);
String line = null;
lnr.setLineNumber(99);
while((line = lnr.myReadLine())!=null)
{
System.out.println(lnr.getLineNumber()+":"+line);
}
lnr.myClose();
}
}
1)繼承屬於擴展形式之一,但不見得是達到彈性設計的最佳方式。
2)在設計中,應該允許行爲可以被擴展,而無須修改現有的代碼。
3)組合和委託可用於在運行時動態地加上新的行爲。
4)除了繼承,裝飾者模式也可以讓我們擴展行爲。
5)裝飾者模式意味着一羣裝飾者類,這些類用來包裝具體組件。
6)裝飾者類反映出被裝飾的組件類型(事實上,他們具有相同的類型,都經過接口或繼承實現)。
7)裝飾者可以在被裝飾者的行爲前面與/或後面加上自己的行爲,甚至將被裝飾者的行爲整個取代掉,而達到特定的目的。
8)可以用無數個裝飾者包裝一個組件。
9)裝飾者一般對組件的客戶是透明的,除非客戶程序依賴於組件的具體類型。
10)裝飾者會導致設計中出現許多小對象,如果過度使用,會讓程序變得很複雜。