設計模式--Decorator---結構型


意圖(Intent)
動態地給一個對象增加一些額外的職責。就增加功
能而言,Decorator模式比生成子類更爲靈活。

      ——《設計模式》GoF

結構圖(stucture)


前面我們用bridgh 模式在不同緯度進行擴展

 

子類復子類,子類何其多
假如我們需要爲遊戲中開發一種坦克,除了各種不同型號
的坦克外,我們還希望在不同場合中爲其增加以下一種或
多種功能:比如紅外線夜視功能,比如水陸兩棲功能,比
如衛星定位功能等等。

 

// 抽象坦克
public abstract class Tank {
public abstract Shot();
public abstract Run();
}

//各種型號
public class T50: Tank {……}
public class T75: Tank {……}
public class T90: Tank {……}
//各種不同功能的組合
public class T50A: T50, IA {…}//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{...}
。。。

我們在加一個功能ID
就會變成I50AD,I50BD,I50CD,I50ABD...
子類將會膨脹。擴展一個功能就要對子類進行擴展膨脹。


動機(Motivation)
  上述描述的問題根源在於我們“過度地使用了繼承來擴展對
象的功能”,由於繼承爲類型引入的靜態特質,使得這種擴
展方式缺乏靈活性;並且隨着子類的增多(擴展功能的增
多),各種子類的組合(擴展功能的組合)會導致更多子
類的膨脹(多繼承)。
如何使“對象功能的擴展”能夠根據需要來動態地實現--功能的綁定都是在運行時?同時
避免“擴展功能的增多”帶來的子類膨脹問題?從而使得任何
“功能擴展變化”所導致的影響將爲最低?



用接口來擴展功能
 

public abstract class Tank
...{
  
abstract void Shot();
  
abstract void Run();
}

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

}

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

}

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

}

 
public interface IA
{
   
void ShotA();
   
void RunA();
}

public class T50:Tank,IA
{   void IA.ShotA();
   
{
}

    
void IA.RunA();


   
public override void Shot()
{

      ShotA();
//功能擴展
// do
      base.Shot();
}

   
public override void Run()
{
     RunA();
   
//do 
    base.Run();
}



  用了 decorator 模式

 

 

public abstract class Tank
    
{
        
public abstract void Shot();
        
public abstract void Run();
    }

 
    
public class T50:Tank
    
{
        
public override void Shot()
        
{}
        
public override void Run()
        
{
        Console.WriteLine(
"開戰了");
        }

    }

    
public abstract class Decorator :Tank//接口繼承--抽象類可以表示接口
    {
        
private Tank _tank;  //Has A 對象組合
 
        
public Decorator (Tank tank)
        
{
            _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
            Console.WriteLine("紅外功能擴展");
            
base.Shot(); 
        }

        
public override void Run()
        
{
            
// 紅外功能擴展
            
// do run
           Console.WriteLine("紅外功能擴展");
            
base.Run();
 
        }

    }

 
 
    
public  class DecoratorB :Decorator
    
{
        
public DecoratorB (Tank tank):base(tank)
        
{
            
        }

    
        
public override void Shot()
        
{  // 水路兩棲擴展
            
// do shot
             Console.WriteLine("水路兩棲擴展");
            
base.Shot(); 
        }

        
public override void Run()
        
{
            
// 水路兩棲功能擴展
            
// do run
            Console.WriteLine("水路兩棲擴展");
            
base.Run();
 
        }

    }

    
public  class DecoratorC :Decorator
    
{
        
public DecoratorC (Tank tank):base(tank)
        
{
            
        }

    
        
public override void Shot()
        
{  // 衛星能擴展
            
// do shot
           Console.WriteLine("衛星能擴展");
            
base.Shot(); 
        }

        
public override void Run()
        
{
            
// 衛星功能擴展
            
// do run
           Console.WriteLine("衛星能擴展");
            
base.Run();
 
        }

    }

 
 
    
public class App
{
    
public static void Main()
{
        Tank tank
=new T50();
        DecoratorA da
=new DecoratorA(tank);//紅外  繼承Tank就是能自己 裝飾
        DecoratorB db=new DecoratorB(da);//紅外,兩棲
        DecoratorC dc=new DecoratorC(db);//紅外,兩棲,衛星。
        dc.Run();
    
}

}

 

Decorator模式的幾個要點
• 通過採用組合、而非繼承的手法, Decorator模式實現了在運行時動
態地擴展對象功能的能力,而且可以根據需要擴展多個功能。避免了
單獨使用繼承帶來的“靈活性差”和“多子類衍生問題”。

• Component類在Decorator模式中充當抽象接口的角色,不應該去實
現具體的行爲。而且Decorator類對於Component類應該透明——換
言之Component類無需知道Decorator類,Decorator類是從外部來擴
展Component類的功能。

• Decorator類在接口上表現爲is
-
a Component的繼承關係,即
Decorator類繼承了Component類所具有的接口。但在實現上又表現
爲has
-
a Component的組合關係,即Decorator類又使用了另外一個
Component類。我們可以使用一個或者多個Decorator對象來“裝飾”一
個Component對象,且裝飾後的對象仍然是一個Component對象。

• Decorator模式並非解決“多子類衍生的多繼承”問題,Decorator模式
應用的要點在於解決“主體類在多個方向上的擴展功能”——是爲“裝飾”
的含義。


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章