前往
大廳
主題

[Design Pattern C#] Decorator Pattern 裝飾者模式 範例

帥氣跳蚤蛋 | 2021-09-05 21:19:26 | 巴幣 22 | 人氣 618

關於此設計模式,網路上已有很多大神做出很詳細的解釋,所以本帥就不獻醜了,
本帥就直接以範例,來呈現我對於裝飾者模式的理解,

在本帥的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();
        }
    }
送禮物贊助創作者 !
0
留言

創作回應

更多創作