[C#]裝飾者模式(Decorator)

[C#]裝飾者模式(Decorator)

目的

當我們有一個介面有很多實作,當我們想要新增一個功能,想要有原本實作的功能,但又想在原本功能前或後面加上一些功能的話,那就可以考慮使用裝飾者模式了。

情境模擬

我們今天有一個下載檔案的介面,同時實作了下載excel和下載pdf的,相關程式碼如下

void Main()
{
	IDownload downloadHelper=new PdfHelper();
	downloadHelper.Download();
	downloadHelper=new ExcelHelper();
	downloadHelper.Download();
}

public interface IDownload
{
	void Download();
}

public class PdfHelper:IDownload
{
	public void Download()
	{
		Console.WriteLine("Pdf Download");
	}
}

public class ExcelHelper : IDownload
{
	public void Download()
	{
		Console.WriteLine("Excel Download");
	}
}

結果

Pdf Download
Excel Download

現在我們有一個需求,我們需要在提供下載檔案之前,必須要存一筆進db,以便之後查詢某檔案的下載量,甚至是下載的會員,但是我們又不想要改原本的程式碼,這時候就可以用上裝飾者模式了,那看一下我新增的程式碼吧

public interface IDownloadDecorator
{
	void Download();
}

public class DownloadDecoratorHelper:IDownloadDecorator
{
	IDownload download; //引用原本的介面
	
	public DownloadDecoratorHelper(IDownload download)
	{
		this.download=download;
	}
	public void Download()
	{
		Console.WriteLine("先存進db"); 調用原本的方法之前,先存進db
		download.Download();
	}
}

而調用端改成如下

void Main()
{
	IDownloadDecorator downloadHelper=new DownloadDecoratorHelper(new PdfHelper());
	downloadHelper.Download();
	downloadHelper=new DownloadDecoratorHelper(new ExcelHelper());
	downloadHelper.Download();
}

結果

先存進db
Pdf Download
先存進db
Excel Download

結論

其實我都刻意的把文字減少,並且把程式碼盡量簡單化,而想表達的也是一些真實世界會遇到的需求改變的情境,因為這些設計模式我也可能是從很複雜的範例看來,而自己想像真實情境並刻意簡單化實做而來的,也是提供給自己參考的,筆者可不想未來想到某個模式,還要先看一堆廢話還有一堆複雜的程式碼,而其實Decorator雖然可以很順利的不改原有的程式碼,來增加新功能,但是如果是原有所有的程式碼都要一併修改的話,那調用端也必定要修改,就躲不掉了,雖然如果我們讓同樣的調用端程式碼散落在各處,那想必整個程式碼就都有很大的問題了,最後其實我們常常聽到的aop或橫切面( cross cutting concerns)都是Decorator的一種實現,有任何想法的話再請指教囉。