我是一名博客園的博主,目前排名第199675位,雖然排名稍稍落後,但這並不影響我向你們學習而後本身吹水。html
在常見的設計模式中,每一個項目或者說產品能夠說裝飾器幾乎必用。設計模式
裝飾器是decorator,別名wrapper,也稱爲包裝器,是建立型、結構型、行爲型分類的結構型,具體有什麼用呢?緩存
說有什麼用,不如直接看下,經過使用裝飾器有什麼結構變化,是如何演化過來的。網絡
經過演化過程,天然知道爲何裝飾器劃分爲結構型,裝飾器解決了什麼問題,做用是啥。app
在流中,有文件流、內存流以及網絡流,他們的讀取方式都不同,可是它們都繼承steam 這個類。 像這樣:ide
public abstract class Stream { protected abstract char Read(int number); protected abstract void seek(int position = 0); protected virtual void write(byte data) { } }
假設讓咱們來分別設計文件流、內存流與網絡流 文件流:學習
public class FileStream: Stream { public virtual void write(byte data) { // 寫入文件 } public override char Read(int number) { throw new NotImplementedException(); } public override void seek(int position = 0) { throw new NotImplementedException(); } }
內存流:this
public class MemoryStream:Stream { public virtual void write(byte data) { // 寫內存流 } public override char Read(int number) { throw new NotImplementedException(); } public override void seek(int position = 0) { throw new NotImplementedException(); } }
網絡流:加密
public class NetworkStream: Stream { public virtual void write(byte data) { // 寫網絡流 } public override char Read(int number) { throw new NotImplementedException(); } public override void seek(int position = 0) { throw new NotImplementedException(); } }
咱們在讀取或者寫入這些流的時候,可能會進行加密或者說緩存。 初版設計,假設咱們以繼承的方式實現。 加密的文件流:spa
public class CryptoBufferedFileStream: FileStream { public override char Read(int number) { base.Read(number); //額外的加密操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的加密操做 base.seek(position); } public override void write(byte data) { //額外的加密操做... base.write(data); } }
加密的內存流:
public class CryptoMemoryStream : MemoryStream { public override char Read(int number) { base.Read(number); //額外的加密操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的加密操做 base.seek(position); } public override void write(byte data) { //額外的加密操做... base.write(data); } }
加密的網絡流
public class CryptoNetworkStream : NetWorkStream { public override char Read(int number) { base.Read(number); //額外的加密操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的加密操做 base.seek(position); } public override void write(byte data) { //額外的加密操做... base.write(data); } }
一樣咱們還要實現緩存流:
//文件流緩衝 public class BufferedFileStream: FileStream { public override char Read(int number) { base.Read(number); //額外的緩衝操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的緩衝操做 base.seek(position); } public override void write(byte data) { //額外的緩衝操做... base.write(data); } } //內存流緩衝 public class BufferedMemoryStream : MemoryStream { public override char Read(int number) { base.Read(number); //額外的緩衝操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的緩衝操做 base.seek(position); } public override void write(byte data) { //額外的緩衝操做... base.write(data); } } //網絡流緩衝 public class BufferedNetworkStream : NetWorkStream { public override char Read(int number) { base.Read(number); //額外的緩衝操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的緩衝操做 base.seek(position); } public override void write(byte data) { //額外的緩衝操做... base.write(data); } }
寫完以後,會發現幾個致命性問題:
1.沒有實現咱們要加密也要緩存,若是要寫下去那麼還須要3個類,感受沒有盡頭。
假設steam 有n 個繼承基礎類,如FileSteam,須要實現m個擴展功能,好比說加密緩衝等。 那麼計算是n(C(m,1),c(m,2)....,C(m,m)) 計算C(m,1),c(m,2)....,C(m,m)=2^m-1 答案是n(2^m-1) 很差意思,個人數學不是很好,若是有錯誤,望請指正。 2.不管加密仍是緩存都是操做byte,並且操做都是read、write與seek,感受有太多類似性代碼了。
根據這兩點咱們改一下。 加密流:
public class CryptoBufferedStream:Stream { Stream stream; public CryptoBufferedStream(Stream stream) { this.stream = stream; } public override char Read(int number) { stream.Read(number); //額外的加密操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的加密操做 stream.seek(position); } public override void write(byte data) { //額外的加密操做... stream.write(data); } }
緩衝流:
public class BufferedMemoryStream : Stream { Stream stream; public BufferedMemoryStream(Stream stream) { this.stream = stream; } public override char Read(int number) { stream.Read(number); //額外的緩衝操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的緩衝操做 stream.seek(position); } public override void write(byte data) { //額外的緩衝操做... stream.write(data); } }
這樣彷佛就看起來舒服不少了,這裏可能會有一個疑惑性的問題, 爲何還要繼承Stream? 裝飾器也叫包裝器,咱們使用CryptoBufferedStream把文件流包裝成了加密文件流,包裝完也是必須是流啊,打包完別忘了打標籤哦。
調用示例:
static void Main(string[] args) { FileStream fileStream = new FileStream(); BufferedMemoryStream bufferedMemoryStream = new BufferedMemoryStream(fileStream); }
這樣就把fileStream給包裝成了bufferedMemoryStream,後面咱們使用的就是BufferedMemoryStream。 這樣咱們沒有失去fileSteam 是流的特性,並且還要另一個好處,既然仍是流,那麼咱們還能夠繼續包裝啊。
CryptoBufferedStream cryptoBufferedStream = new CryptoBufferedStream(bufferedMemoryStream);
這時候咱們即加密了,也緩衝了,實現了咱們原來沒有寫的3個類。 這裏發現一個問題,那就是stream這個屬性在CryptoBufferedStream 和 BufferedMemoryStream 都存在。 其實提取和不提取都沒有關係,可是對咱們寫代碼的人來講,每次都要去寫個能夠提取出來的字段,是至關不舒服的,並且還不開心。 終版: 將stream屬性提取出來,提取到DecoratorStream中。
public abstract class DecoratorStream: Stream { protected Stream stream; public DecoratorStream(Stream stream){ this.stream = stream; } } public class CryptoBufferedStream: DecoratorStream { public CryptoBufferedStream(Stream stream):base(stream) { } public override char Read(int number) { stream.Read(number); //額外的加密操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的加密操做 stream.seek(position); } public override void write(byte data) { //額外的加密操做... stream.write(data); } } public class BufferedMemoryStream : DecoratorStream { public BufferedMemoryStream(Stream stream):base(stream) { } public override char Read(int number) { stream.Read(number); //額外的緩衝操做 throw new NotImplementedException(); } public override void seek(int position) { //額外的緩衝操做 stream.seek(position); } public override void write(byte data) { //額外的緩衝操做... stream.write(data); } }
看起來就舒服不少了。 爲何看起來會舒服,一張圖解釋出來。 假設steam 有n 個繼承基礎類,如FileSteam,須要實現m個擴展功能,好比說加密緩衝等。按照裝飾器的計算方式是:m+1 n(2^m-1)與m+1 二者的方式對比顯而易見啊,如今能夠證實爲何裝飾器是一個結構模式了吧。 至於做用,能夠看出,能夠解決繼承致使的子類膨脹問題。
後面補上,畫圖累啊。
由於n(2^m-1)在n>1或者m大於1的狀況下,n(2^m-1)=>m+1,且僅當m=2時候二者相等,因此做用爲:能夠解決繼承致使的子類膨脹問題,膨脹問題屬於結構問題,解決的是結構問題,因此歸屬爲結構型。
原文出處:https://www.cnblogs.com/aoximin/p/12078650.html