/*
* 使用場景:遊戲中需要開發坦克,坦克具有不同型號【如T50,T70,T90等】,而且希望不同型號的坦克具有一種或者多種功能[紅外,水陸兩用,衛星定位等]。
* 通常的解決方案:
* public abstract class Tank(){}
* T50:Tank T70:Tank T90:Tank
* IA IB IC //紅外,水陸,衛星定位的功能接口
* T50A:T50,IA T50B:T50,IB T50C:T50,IC
* T50AB:T50,IA,IB .....
* 由此,存在的問題,當需要爲一種類型[T50系列]增加一個功能[如對空導彈],就需要修改和T50相關的所有類。
* 也就是說,這種解決方案存在一個問題,那就是類數目的指數級別增長,當需求改變是,需要更改的代價很大。
*
* 問題深入分析:
* 過度使用了繼承來擴展對象的功能。由於繼承爲類型引入的靜態特質,使得這種擴展方式缺乏靈活【編譯的時候生成,而不是運行的時候生成】。
* 並且,隨着子類的增多,各種子類的組合導致子類的膨脹。
* 目標:“對象功能的擴展”能夠根據需求來動態地【運行的時候實現】實現,同事避免“擴展功能的增多”帶來子類的膨脹問題。
*
* 意圖:動態地給一個對象增加一些額外的職責。
*
* UML圖說明:
* Component-----Tank,
* ConcreteConponent-----T50,T70...
* Decorator----Decorator
* ConcreteDecoratorA----DecoretorA, ConcreteDecoratorB----DecoretorB
*
*/
namespace sington1
{
public abstract class Tank
{
public abstract void Shot();
public abstract void Run();
}
public class T50 : Tank
{
public T50()
{ System.Console.WriteLine("T50"); }
public override void Shot()
{
}
public override void Run()
{
}
}
public class T70 : Tank
{
public T70()
{ System.Console.WriteLine("T70"); }
public override void Shot()
{
}
public override void Run()
{
}
}
/*Decorator繼承了Tank,這裏實際上是繼承了他的接口,而不是具體類的繼承。
*
*/
public abstract class Decorator : Tank
{
private Tank _tank;//對象組合
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();
System.Console.WriteLine("紅外功能擴展");
}
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();
System.Console.WriteLine("衛星定位功能擴展");
}
public override void Run()
{
//衛星定位功能擴展
//do Run
base.Run();
}
}
/*通過採用組合,而非繼承的手法,Decorator模式實現了運行時動態地擴展對象功能的能力,而且可以根據需求擴展多個功能,
* 避免了單獨似乎用繼承帶來的“靈活性差”和“多子類衍生問題”。
*
*/
class decorator
{
public static void Main()
{
Tank tank = new T50(); //得到T50坦克
DecoratorA da = new DecoratorA(tank); //裝飾爲具有紅外功能的T50
DecoratorB dab = new DecoratorB(da); //裝飾da爲具有衛星定位功能,還可以對該坦克進行擴展。
dab.Shot();
/*輸出結果:
* T50
* 紅外功能擴展
* 衛星定位功能擴展
*/
System.Console.WriteLine("End");
}
}