裝飾器模式

場景:假設每次咱們去超市購物,咱們都會推一個購物車,有水果、蔬菜、肉類三種商品,提供給咱們選擇,那麼這時候,若是使用裝飾器模式,應該如何實現?ide

1.什麼是裝飾器模式測試

首先咱們知道,若是想要給一個類或者對象添加一些行爲,能夠經過繼承這樣的機制,經過子類繼承父類的方式,使得子類在擁有本身的行爲的時候,同時也繼承了父類的一些方法。可是繼承的方式,使得子類和父類之間的耦合增大了,而且這種方法是靜態的,用戶不能控制增長行爲的方式和時機。ui

還有一種方式是使用關聯機制,將一個類對象嵌入到另外一個對象中,由另外一個對象來決定是否調用嵌入對象的行爲,以便擴展本身的行爲,這種嵌入的對象就成爲裝飾器spa

那麼裝飾器模式動機就是:裝飾模式能夠在不須要創造更多子類的狀況下,將對象的功能加以擴展。這就是裝飾模式的模式動機。設計

裝飾器模式的設計圖以下:code

 

  • Component: 抽象構件
  • ConcreteComponent: 具體構件
  • Decorator: 抽象裝飾類
  • ConcreteDecorator: 具體裝飾類

 

2.實現場景對象

根據這個設計圖,咱們能夠設計一下上面場景的實現blog

.原始類-就是那個購物車(shoppingCart繼承

.繼承類A-這裏沒有繼承,因此這部分不須要,若是之後須要對購物車的種類進行再細緻的劃分,可使用圖片

.裝飾器基類(BaseDecorator)

.裝入水果、蔬菜、肉類就對應下面的三個裝飾器ABC

實現代碼:

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.總結

優勢

  裝飾這模式和繼承的目的都是擴展對象的功能,但裝飾者模式比繼承更靈活

  經過使用不一樣的具體裝飾類以及這些類的排列組合,設計師能夠創造出不少不一樣行爲的組合

  裝飾者模式有很好地可擴展性

缺點

  裝飾者模式會致使設計中出現許多小對象,若是過分使用,會讓程序變的更復雜。而且更多的對象會是的差錯變得困難,特別是這些對象看上去都很像。 

使用場景

  須要擴展一個類的功能或給一個類增長附加責任。

  須要動態地給一個對象增長功能,這些功能能夠再動態地撤銷。

  須要增長由一些基本功能的排列組合而產生的很是大量的功能

相關文章
相關標籤/搜索