2013年12月1日 星期日

C# Design Pattern - Decorator 裝飾者模式

Decorator的特性是採用組合、而非繼承,實現運行時動態地擴展物件功能的能力,而且可以
根據需要擴展多個功能。避免單獨使用繼承而產生靈活性差和"多子類別衍生問題。但它最根本的作用是在於裝飾。

例如開發一個報表功能可能只有顯示和下載的兩個功能,
之後又要加入顯示時先檢查是否有權限、下載前也要檢查權限、權限檢查後,判斷系統日期是否為月底。
所以為了要解決新增功能問題,不要修改原本的程式碼,又可以擴充,Decorator就是符合開發封閉原則,對修改封閉,對擴充開放,
藉以降低系統可能的錯誤風險,使用Decorator模式的組合特性來達到動態擴充相關功能。

假如在遊戲中開發一種坦克,除了各種不同型號的坦克外,還希望在不同場合中增加一種或多種功能,比如紅外線夜視、水陸兩棲,衛星定位等等。



建立抽象坦克類別
namespace Decorator
{
    public abstract class Tank
    {
        public abstract void Shot();
        public abstract void Run();
    }
}


namespace Decorator
{
    public class T50 : Tank
    {
        public override void Shot()
        {
            Console.WriteLine("T50坦克平均每秒射擊5發子彈");
        }

        public override void Run()
        {
            Console.WriteLine("T50坦克平均每時運行30公里");
        }
    }

}

然後按照上面的結構,一樣創造了T75、790的場克,功能結構也是依不同的功能性而產生不同的陳述結構

實現介面繼承,非實現繼承,組合物件
namespace Decorator
{
    public abstract class DecoratorTank
    {
        private Tank tank;

        public Decorator(Tank tank)
        {
            this.tank = tank;
        }

        public override void Shot()
        {
            tank.Shot();
        }

        public override void Run()
        {
            tank.Run();
        }
    }

}

產生各種不同的功能並擴展,同時可依需求限制其功能,讓各種不同的坦克有等級上的差別
namespace Decorator
{
    public class DecoratorA : Decorator
    {
        public DecoratorA(Tank tank)
            : base(tank)
        {
        }

        public override void Shot()
        {
            //功能擴展 且有紅外功能
            base.Shot();
        }

        public override void Run()
        {
            base.Run();
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Tank tank = new Tank();
        DecoratorA da = new DecoratorA(tank); //且有紅外功能
        DecoratorB db = new DecoratorB(da);   //且有紅外和水陸兩棲功能
        DecoratorC dc = new DecoratorC(db);   //且有紅外、水陸兩棲、衛星定們三種功能
        dc.Shot();
        dc.Run();
    }

}

Decorator需要擴展一個類的功能,或給一個類增加附加責任,動態地給一個物件增加功能,這些功能可以動態撤銷。也可以增加由一些基本功能的排列組合而產生的非常大量的功能。

Decorator在.NET(Stream)中的應用,透過.Net讓Decorator模式省略了抽象裝飾角色(Decorator):



下面的程式中BufferedStream擴展了緩衝的功能、CryptoStream擴展了緩衝,加密的功能:

class Program
{
    public static void Main(string[] args)
    {
        MemoryStream ms = new MemoryStream (new byte[] { 100, 456, 864, 222, 567 });
        BufferedStream BufferedStream buff = new BufferedStream(ms);
        CryptoStream CryptoStream crypto = new CryptoStream(buff);
    }
}

所以透過.NET的Library呈現,可以看到BufferedStream是繼承於Stream類別,依然可以達到同樣的效果。

-雲遊山水為知已逍遙一生而忘齡- 電腦神手

沒有留言:

張貼留言