關於此設計模式,網路上已有很多大神做出很詳細的解釋,所以本帥就不獻醜了,
本帥就直接以範例,來呈現我對於裝飾者模式的理解,
在本帥的GitHub:
有完整的範例程式碼,
此範例展示了2個同樣功能的程式,
呈現使用裝飾者模式,與無使用裝飾者模式的撰寫差別
此範例的程式有兩個專案,
1.Non Design Pattern: 無使用裝飾者模式
2.C Sharp Decorator Pattern Exercise-Design Pattern: 使用裝飾者模式
由於篇幅限制,本文只講解裝飾者模式的範例,
無使用裝飾者模式的範例,請看本帥的GitHub,
自行比較兩種設計方法的差異
本範例是以txt與csv兩個檔案格式,做為被裝飾者,
在檔案中寫入設定的字串、今天的日期、固定字串"Hello, World!"與關閉檔案,
4個行為作為裝飾者,
在決定好被裝飾者後,可自由的加入數量不等裝飾,
在最後執行Operation()方法,就會依序執行裝飾的行為,
若今天有新的功能需要加入(ex:寫入今天的時間),
只要繼承裝飾者的抽象類別進行實作,即可擴充功能.
裝飾者模式想要呈現的行為:
BaseFile txtFile = new TxtFile("txtTest"); //建立一個txt檔
txtFile = new WriteString(txtFile, "跳蚤是大帥哥"); //寫入"跳蚤是大帥哥"
txtFile = new WriteDate(txtFile); //寫入今天日期
txtFile = new WriteHelloWorld(txtFile); //寫入固定字串"Hello, World!"
txtFile = new CloseFile(txtFile); //關閉txt檔案
txtFile.Operation(); //執行裝飾者模式
BaseFile csvFile = new CsvFile("csvTest"); //建立一個csv檔
csvFile = new WriteDate(csvFile); //寫入今天日期
csvFile = new WriteString(csvFile, "跳蚤真他媽的帥"); //寫入"跳蚤真他媽的帥"
csvFile = new CloseFile(csvFile); //關閉csv檔案
csvFile.Operation(); //執行裝飾者模式
首先定義了一個BaseFile的抽象類別,此類別是所有裝飾者與被裝飾者,繼承的類別 public abstract class BaseFile
{
protected string filename;
public abstract StreamWriter Operation();
}
接下來建立被裝飾者的類別TxtFile與CsvFile,皆繼承自BaseFile,
這2個類別分別會建立txt與csv檔案
此類別為基底類別,給之後的FileOperation進行裝飾
public class TxtFile : BaseFile //建立TXT檔,被裝飾者
{
public TxtFile(string name)
{
base.filename = name + ".txt";
}
public override StreamWriter Operation() => new StreamWriter(this.filename, true);
}
public class CsvFile : BaseFile //建立CSV檔,被裝飾者
{
public CsvFile(string name)
{
base.filename = name + ".csv";
}
public override StreamWriter Operation() => new StreamWriter(this.filename, true, Encoding.Unicode);
}
建立被裝飾者的基底抽象類別,也繼承自BaseFile,
所有的裝飾者皆須繼承此類別,
此類別有一個ExtraOperation的抽象方法,裝飾者的行為在此實作,
會由Operation()調用ExtraOperation()
public abstract class FileOperation : BaseFile
{
protected BaseFile baseFile;
protected StreamWriter sw;
public FileOperation(BaseFile b) //進行裝飾
{
baseFile = b;
}
public abstract void ExtraOperation();
public override StreamWriter Operation()
{
sw = baseFile.Operation(); //呼叫被裝飾者
ExtraOperation(); //執行自己的方法
return sw;
}
}
開始實作裝飾者類別,在此分為四種行為:
1.在檔案中寫入設定的字串
2.在檔案中寫入今天的日期
3.在檔案中寫入固定字串"Hello, World!"
4.關閉檔案
public class WriteString : FileOperation //將設定的字串寫入檔案
{
private string WriteStr;
public WriteString(BaseFile bf, String str) : base(bf) //加入裝飾
{
this.WriteStr = str; //要寫入檔案的字串
}
public override void ExtraOperation()
{
base.sw.WriteLine(WriteStr);
}
}
public class WriteDate : FileOperation //將今天的日期寫入檔案
{
public WriteDate(BaseFile bf) : base(bf) { } //加入裝飾
public override void ExtraOperation()
{
DateTime now = DateTime.Today;
base.sw.WriteLine(now.ToString("yyyy/MM/dd"));
}
}
public class WriteHelloWorld : FileOperation //寫入固定字串"Hello, World!"
{
public WriteHelloWorld(BaseFile bf) : base(bf) { }
public override void ExtraOperation()
{
base.sw.WriteLine("Hello, World!");
}
}
public class CloseFile : FileOperation //關閉檔案
{
public CloseFile(BaseFile bf) : base(bf) { }
public override void ExtraOperation()
{
base.sw.Close();
}
}