場景:假設每次咱們去超市購物,咱們都會推一個購物車,有水果、蔬菜、肉類三種商品,提供給咱們選擇,那麼這時候,若是使用裝飾器模式,應該如何實現?ide
1.什麼是裝飾器模式測試
首先咱們知道,若是想要給一個類或者對象添加一些行爲,能夠經過繼承這樣的機制,經過子類繼承父類的方式,使得子類在擁有本身的行爲的時候,同時也繼承了父類的一些方法。可是繼承的方式,使得子類和父類之間的耦合增大了,而且這種方法是靜態的,用戶不能控制增長行爲的方式和時機。ui
還有一種方式是使用關聯機制,將一個類對象嵌入到另外一個對象中,由另外一個對象來決定是否調用嵌入對象的行爲,以便擴展本身的行爲,這種嵌入的對象就成爲裝飾器spa
那麼裝飾器模式的動機就是:裝飾模式能夠在不須要創造更多子類的狀況下,將對象的功能加以擴展。這就是裝飾模式的模式動機。設計
裝飾器模式的設計圖以下:code
2.實現場景對象
根據這個設計圖,咱們能夠設計一下上面場景的實現blog
①.原始類-就是那個購物車(shoppingCart)繼承
②.繼承類A-這裏沒有繼承,因此這部分不須要,若是之後須要對購物車的種類進行再細緻的劃分,可使用圖片
③.裝飾器基類(BaseDecorator)
④.裝入水果、蔬菜、肉類就對應下面的三個裝飾器A、B、C
實現代碼:
ShoppingCart.cs
public class ShoppingCart
{ public virtual void Show() { } }
BaseDecorator.cs
public class BaseDecorator:ShoppingCart
{ protected ShoppingCart _shoppingCart; public BaseDecorator(ShoppingCart shoppingCart) { _shoppingCart = shoppingCart; } public override void Show() { if (_shoppingCart != null) { base.Show(); } } }
FruitsDecorator.cs
public class FruitsDecorator:BaseDecorator { public FruitsDecorator(ShoppingCart shoppingCart) : base(shoppingCart) { } public void addFruits() { Console.WriteLine("加入了水果。"); } public override void Show() { base.Show(); addFruits(); } }
MeatsDecorator.cs
public class MeatsDecorator : BaseDecorator { public MeatsDecorator(ShoppingCart shoppingCart) : base(shoppingCart) { } public void addMeat() { Console.WriteLine("加入了肉。"); } public override void Show() { base.Show(); addMeat(); } }
VegetablesDecorator.cs
public class VegetablesDecorator : BaseDecorator
{ public VegetablesDecorator(ShoppingCart shoppingCart) : base(shoppingCart) { } public void addVegetable() { Console.WriteLine("加入蔬菜。"); } public override void Show() { base.Show(); addVegetable(); } }
Program.cs
ShoppingCart sc = new ShoppingCart();
BaseDecorator bd = new BaseDecorator(sc); //添加水果 FruitsDecorator fd = new FruitsDecorator(bd); fd.Show(); //添加肉 MeatsDecorator md = new MeatsDecorator(fd); md.Show(); //添加蔬菜 VegetablesDecorator vd = new VegetablesDecorator(md); vd.Show();
測試執行:
3.其餘應用場合
在C#當中,應用裝飾器的場景是蠻多的,比較典型的是System.IO.Stream
圖片從http://blog.jobbole.com/78077/截取
其餘場景參考:http://wangqingpei557.blog.51cto.com/1009349/621137/ 不錯
例如使用壓縮流的時候
//壓縮數據 static Byte[] Compress(Byte[] data) { //壓縮入這個內存流 using (MemoryStream target = new MemoryStream()) { using (GZipStream gs = new GZipStream(target,CompressionMode.Compress,true)) { //把數據寫入到壓縮流當中 //具體實現略 } return target.ToArray(); } }
4.總結
優勢:
裝飾這模式和繼承的目的都是擴展對象的功能,但裝飾者模式比繼承更靈活
經過使用不一樣的具體裝飾類以及這些類的排列組合,設計師能夠創造出不少不一樣行爲的組合
裝飾者模式有很好地可擴展性
缺點:
裝飾者模式會致使設計中出現許多小對象,若是過分使用,會讓程序變的更復雜。而且更多的對象會是的差錯變得困難,特別是這些對象看上去都很像。
使用場景:
須要擴展一個類的功能或給一個類增長附加責任。
須要動態地給一個對象增長功能,這些功能能夠再動態地撤銷。
須要增長由一些基本功能的排列組合而產生的很是大量的功能