定義
裝飾模式(Decorator Pattern),動態(組合)地給一個物件新增(擴充套件)一些額外的職責,就增加功能來說,裝飾模式比生成子類更為靈活。
結構圖
裝飾模式結構圖
參與者
Component:定義一個物件介面,可以給這些物件動態地新增職責。ConcreteComponent:定義一個物件,可以給這個物件新增一些職責。 Decorator:維持一個指向Component的指標,並定義一個與Component介面一致的介面。 ConcreteDecorator:負責向ConcreteComponent新增功能。 在裝飾模式中,Decorator定義了一個裝飾介面類。因為Decorator與ConcreteComponent繼承同一個介面,所以繼承Decorator的類ConcreteDecorator可以使用ConcreteComponent的方法,再在ConcreteDecorator裡面加入一些新的方法,也就是裝飾,就成為了一個包裝好的裝飾類。
程式碼示例
下面我們用。net中“Stream-流”的設計來說明此模式,具體程式碼如下:
//流-抽象類
public abstract class Stream
{
//設定當前流中的位置
public abstract long Seek(long offset, System。IO。SeekOrigin origin);
//從當前流讀取位元組序列
public abstract int Read(byte[] buffer, int offset, int count);
//向當前流中寫入位元組序列
public abstract void Write(byte[] buffer, int offset, int count);
}
//檔案流
public class FileStream : Stream
{
public override long Seek(long offset, System。IO。SeekOrigin origin)
{
//檔案流具體實現
return 0;
}
public override int Read(byte[] buffer, int offset, int count)
{
//檔案流具體實現
return 0;
}
public override void Write(byte[] buffer, int offset, int count)
{
//檔案流具體實現
}
}
//網路流
public class NetworkStream : Stream
{
public override long Seek(long offset, System。IO。SeekOrigin origin)
{
//網路流具體實現
return 0;
}
public override int Read(byte[] buffer, int offset, int count)
{
//網路流具體實現
return 0;
}
public override void Write(byte[] buffer, int offset, int count)
{
//網路流具體實現
}
}
//繼承Stream,遵循規範
public abstract class DecoratorStream : Stream
{
//組合(維持一個指向Stream的指標)
protected Stream strm;
public DecoratorStream(Stream strm)
{
this。strm = strm;
}
}
//加密流,擴充套件操作
public class CryptoStream : DecoratorStream
{
public CryptoStream(Stream strm) : base(strm)
{
}
public override long Seek(long offset, System。IO。SeekOrigin origin)
{
//。。。。具體加密操作(加密就是AddedBehavior,擴充套件了檔案流,網路流等;動態決定)
strm。Seek(offset, origin);//主體操作
return 0;
}
public override int Read(byte[] buffer, int offset, int count)
{
//。。。。具體加密操作
strm。Read(buffer, offset, count);
return 0;
}
public override void Write(byte[] buffer, int offset, int count)
{
//。。。。具體加密操作
strm。Write(buffer, offset, count);
}
}
//快取流,擴充套件操作
public class BufferedStream : DecoratorStream
{
public BufferedStream(Stream strm) : base(strm)
{
}
public override long Seek(long offset, System。IO。SeekOrigin origin)
{
//。。。。具體快取操作(快取就是AddedBehavior,擴充套件了檔案流,網路流等;動態決定)
strm。Seek(offset, origin);//主體操作
return 0;
}
public override int Read(byte[] buffer, int offset, int count)
{
//。。。。具體快取操作
strm。Read(buffer, offset, count);
return 0;
}
public override void Write(byte[] buffer, int offset, int count)
{
//。。。。具體快取操作
strm。Write(buffer, offset, count);
}
}
public class Client
{
public static void Main()
{
//加密檔案流(執行時裝配)
Stream s1 = new CryptoStream(new FileStream());
//快取網路流
Stream s2 = new BufferedStream(new NetworkStream());
//加密快取網路流
Stream buffer = new CryptoStream(new BufferedStream(new NetworkStream()));
}
}
總結
裝飾模式的特點:
比靜態類更靈活。使用裝飾模式可以很容易地向物件新增職責的方式。可以用新增和分離的方法,對裝飾在執行時新增和刪除職責。相比之下,繼承機制要求為每個新增的職責建立一個新的子類。這會產生很多新的類,並會增加系統的複雜度。
使用裝飾模式可以很容易地重複新增一個特性,而兩次繼承特性類則極容易出錯。
為了避免處理頂層的類有太多的特徵。裝飾模式下,你可以定義一個簡單的類,並用裝飾類給它逐漸地新增功能。這樣可以從簡單的部件組合出複雜的功能,具有低依賴性和地複雜性。