結構型模式:Decorator 裝飾模式

                                                           結構型模式:Decorator 裝飾模式

1、子類復子類,子類何其多
  1)假如咱們須要爲遊戲中開發一種坦克,除了各類不一樣型號的坦克外,咱們還但願在不一樣場合中爲其增長如下一種或多種功能:好比紅外線夜視功能,好比水陸兩棲功能,好比衛星定位功能等等。
  2)這是遊戲的設計坦克,所以這個定位要定位在軟件的組件的設計。設計模式

//坦克抽象類
public abstract class Tank
{
  public abstract void Shot();
  public abstract void Run();
}
//各類型號
public class T50 : Tank
{
  //.....
}
public class T75 : Tank
{
  //.....
}
public class T90 : Tank
{
  //.....
}
//各類不一樣功能的組合
public class T50A : T50, IA
{
  //......
}
public class T50B : T50, IB
{
  //......
}
public class T50C : T50, IC
{
  //......
}
public class T50AB : T50, IA, IB
{
  //......
}
public class T50BC : T50, IB, IC
{
  //......
}
public class T50ABC : T50, IA, IB, IC
{
  //......
}
......
  3)分析:隨着功能的擴展(各類功能的排列組合),子類會急劇膨脹。一個微小的變更就帶來了很大的震動,
  這時候咱們引入了裝飾(Decorator)模式解決這類問題。
 
2、動機(Motivation)
  1)上述描述的問題根源在於咱們「過分地使用了繼承來擴展對象的功能」,因爲繼承爲類型引入的靜態特質,使得這種擴展方式缺少靈活性;而且隨着子類的增多(擴展功能的增多),各類子類的組合(擴展功能的組合)會致使更多子類的膨脹(多繼承)。
  2)如何使「對象功能的擴展」可以根據須要來動態地實現?同時避免「擴展功能的增多」帶來的子類膨脹問題?從而使得任何「功能擴展變化」所致使 的影響將爲最低?
 
3、意圖(Intent)
  動態地給一個對象增長一些額外的職責(功能)。就增長功能而言,Decorator模式比生成子類更爲靈活。
                                                                                     ——《設計模式》GoF
 
4、實例:擴展坦克在不一樣場合下的功能
  1)下面用類繼承的解決辦法,擴展多種功,會致使子類過多
//坦克的抽象類
public abstract class Tank
{
  //各類功能
  public abstract void Shot();
  public abstract void Run();
}網絡

//各類型號的坦克
public class T50 : Tank
{
  public override void Shot()
  {
  }
  public override void Run()
  {
  }
}ide

public class T75 : Tank
{
  public override void Shot()
  {
  }
  public override void Run()
  {
  }
}this

public class T90 : Tank
{
  public override void Shot()
  {
  }
  public override void Run()
  {
  }
}加密

//擴展功能的接口
public interface IA
{
  //擴展功能
  void ShotA();
  void RunA();
}設計

public class T50 : Tank, IA
{
  private void IA.ShotA()
  {
  }
  private void IA.RunA()
  {
  }
 
  public override void Shot()
  {
    this.ShotA(); //功能擴展
    //do shot...
    base.Shot();
  }
 
  public override void Run()
  {
    this.RunA();//功能擴展
    //do run...
    base.Run();
  }
}對象

  2)應用Decorator模式設計功能擴展
//坦克的抽象類
public abstract class Tank
{
  //各類功能
  public abstract void Shot();
  public abstract void Run();
}繼承

//T50型號的坦克
public class T50 : Tank
{
  public override void Shot()
  {
  }
  public override void Run()
  {
  }
}接口

//擴展功能
public abstract class Decorator : Tank //實際是接口繼承
{
  private Tank _tank;  //Has-A 對象組合
 
  public Decorator(Tank tank)
  {
    this._tank = tank;
  }
 
  public override void Shot()
  {
    _tank.Shot();
  }
 
  public override void Run()
  {
    _tank.Run();
  }
}遊戲

public class DecoratorA : Decorator
{
  //構造器是不繼承的,要進行相應設置
  public DecoratorA(Tank tank) : base(tank)
  {
  }
 
  public override void Shot()
  {
    //紅外功能擴展
    //do shot...
    base.Shot();
  }
 
  public override void Run()
  {
    //紅外功能擴展
    //do run...
    base.Run();
  }
}

public class DecoratorB : Decorator
{
  //構造器是不繼承的,要進行相應設置
  public DecoratorB(Tank tank) : base(tank)
  {
  }
 
  public override void Shot()
  {
    //水陸兩棲功能擴展
    //do shot...
    base.Shot();
  }
 
  public override void Run()
  {
    //水陸兩棲功能擴展
    //do run...
    base.Run();
  }
}

public class DecoratorC : Decorator
{
  //構造器是不繼承的,要進行相應設置
  public DecoratorC(Tank tank) : base(tank)
  {
  }
 
  public override void Shot()
  {
    //衛星定位功能擴展
    //do shot...
    base.Shot();
  }
 
  public override void Run()
  {
    //衛星定位功能擴展
    //do run...
    base.Run();
  }
}

//客戶程序
class App
{
  public static void Main()
  {
    Tank tank = new T50();
   
    DecoratorA da = new DecoratorA(tank);//紅外
   
    DecoratorB db = new DecoratorB(da);//紅外,兩棲
   
    DecoratorC dc = new DecoratorB(db);//紅外,兩棲,衛星定位
  }
}

5、Decorator模式的幾個要點   1)經過採用組合、而非繼承的手法,Decorator模式實現了在運行時動態地擴展對象功能的能力,並且能夠根據須要擴展多個功能。避免了單獨使用繼承帶來的「靈活性差」和「多子類衍生問題」。   2)Component類在Decorator模式中充當抽象接口的角色,不該該去實現具體的行爲。並且Decorator類對於Component類應該透明——換言之Component類無需知道Decorator類,Decorator類是從外部來擴展Component類的功能。   3)Decorator類在接口上表現爲is-a Component的繼承關係,即Decorator類繼承了Component類所具備的接口。但在實現上又表現爲has-a Component的組合關係,即Decorator類又使用了另一個Component類。咱們可使用一個   或者多個Decorator對象來「裝飾」一個Component對象,且裝飾後的對象仍然是一個Component對象。   4)Decorator模式並不是解決「多子類衍生的多繼承問題」,Decorator模式應用的要點在於解決「主體類在多個方向上的擴展功能」——是爲「裝飾」的含義。   6、.NET框加中的Decorator應用 抽象接口:           Stream(流) 實體類:繼承Stream           FileStream(文件流)           NetworkStream(網絡流)           MemoryStrem(內存流) 裝飾對象:繼承Stream,內部還包括一個Stream字段           BufferedStream(緩衝功能擴展)           CryptoStream(加密功能擴展)

相關文章
相關標籤/搜索