設計模式學習-裝飾模式

  維護系統,需求變更是程序猿心中永遠的痛...

  (虛擬場景)這不,老大剛過來說,XX,你需要把XX系統的站內短信息系統修改一下,接收人打開後,修改短信息狀態爲已讀。

  我:“好的,沒問題,這就改。”

  先看看之前的代碼,恩,貌似很簡單,直接操作數據庫修改狀態好了。 

View Code 
    public class MessageManage 
    {
        public string GetMessage() 
        {
            return "短消息XXXXXXXXXX";
        }
    }

    public class Client 
    {
        static void Main() 
        {
            MessageManage msgManage = new MessageManage();
            Console.WriteLine(msgManage.GetMessage());
        }

  修改後的代碼:

View Code 
    public class MessageManage 
    {
        public string GetMessage() 
        {
            return "短消息XXXXXXXXXX";
        }

        public void ChangeStatus() 
        {
            Console.WriteLine("短消息狀態修改");
        }
    }

    public class Client 
    {
        static void Main() 
        {
            MessageManage msgManage = new MessageManage();
            msgManage.ChangeStatus();
            Console.WriteLine(msgManage.GetMessage());
        }

  代碼測試完,提交了,老大忽然又跑來說,那啥,我剛忘記了,查看完短消息後要保存操作日誌到TXT文檔裏。 

  我心裏說:"這些需求早點怎麼不提,應該是設計階段要解決的,亂碼三千字...省略...."。沒辦法,有需求就要改,拿人錢財,替人消災。
  作爲一個有思想的,想進步的猴子,我覺得我不能一而再,再爾三的違反開閉原則。趁現在短消息系統還比較簡單,我決定重構短消息這塊的代碼。功能需求不斷增加,用個什麼設計模式好呢?記得有一個動態的給對象增加功能的模式。

模式概述: 

Decorator Pattern,又叫裝飾模式、裝飾者模式。裝飾模式是在不必改變原類文件和使用繼承的情況下,動態的擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。

UML類圖:


其中類與對象之間的關係爲:

  • Component類
    定義裝飾對象與被裝飾對象的共同的裝飾行爲

  • ConcreateComponent類
    被裝飾的對象

  • Decorator類
    裝飾類的抽象類,包含了Component類的實例(表明將來的具體裝飾類都有一個明確的裝飾對象)並實現Component類中裝飾對象和被裝飾對象的共同行爲,

  • ConcreteDecorator類 
    具體的裝飾類,實現了Decorator類

 現在,我們就按裝飾模式重構一下我們的代碼:

View Code 
    public abstract class Component 
    {
        public abstract string GetMessage();
    }

    public class MessageManage : Component 
    {
        public override string GetMessage()
        {
            return "短消息XXXXXXXXXX";
        }
    }

    public abstract class Decorator : Component 
    {
        private Component _com;

        public Decorator(Component com) 
        {
            this._com = com;
        }

        public override string GetMessage()
        {
            return _com.GetMessage();
        }
    }

    public class ConcreteDecoratorA : Decorator 
    {
        public ConcreteDecoratorA(Component com)
            : base(com)
        {
        }

        private void changeStatus() 
        {
            Console.WriteLine("短消息狀態修改");
        }

        public override string GetMessage()
        {
            this.changeStatus();
            return base.GetMessage();
        }
客戶端調用:
View Code 
        static void Main()
        {
            MessageManage msg = new MessageManage();
            ConcreteDecoratorA actionA = new ConcreteDecoratorA(msg);
            Console.WriteLine(actionA.GetMessage());
            Console.ReadLine();
現在我們增加保存日誌到Txt的功能,原代碼不需要修改,新增代碼如下:
View Code 
    public class ConcreteDecoratorB : Decorator
    {
        public ConcreteDecoratorB(Component com)
            : base(com)
        {
        }

        private void writeLog()
        {
            Console.WriteLine("保存操作日誌到Txt文件");
        }

        public override string GetMessage()
        {
            this.writeLog();
            return base.GetMessage();
        }
客戶端代碼變爲:
View Code 
        static void Main()
        {
            MessageManage msg = new MessageManage();
            ConcreteDecoratorA actionA = new ConcreteDecoratorA(msg);
            ConcreteDecoratorB actionB = new ConcreteDecoratorB(actionA);
            Console.WriteLine(actionB.GetMessage());
            Console.ReadLine();
這樣,我們比較好的實現了對修改的關閉,對擴展的開放,以後再增加比如打開短消息,通知原用戶的功能等也沒有問題了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章