1. 程式人生 > >C# - 設計模式 - 策略模式

C# - 設計模式 - 策略模式

變化 繼承 否則 www. 默認 ref 獨立 UNC int

策略模式

問題場景

多個類型都有一些共同的屬性和方法,可以稱這些成員為行為,為了避免重復在多個類型中編碼相同部分的行為,應考慮將這些行為定義在抽象類(超類)中,利用繼承時多個類型可以共享這些行為。比如定義一個超類Animal,具有Eyes屬性和Run方法,老虎和獅子都從Animal派生,所以可以靠繼承得到Animal定義的行為。但是今後需求變更,可能會增加一個袋鼠,袋鼠只會跳不會跑,所以當袋鼠也具備Run時就顯得不合理。再次設計類型結構時,可能會考慮接口,比如將Run和Jump定義成接口IRunable和IJumpable,以插拔的形式插入需要這些行為的動物中。可是這樣做,那麽每一個動物都需要實現插拔在它們上面的接口所定義方法。所以繼承沒有使類型結構變得合理,而插拔也並沒有防止重復編碼的問題。現在可以考慮策略模式,行為接口IRun由獨立的類型Run來實現,將Run作為需要奔跑行為的類型的一個屬性進行存取,這樣,Run類實現了奔跑的行為,所以需要奔跑行為的動物就不再需要重復編碼奔跑行為,而是調用IRun類的實現就可以了。

總結模式

找出類型中的不易變化的行為和可能變化的行為,將可能在未來變化的行為提煉成獨立的類型,這些獨立的類型應該是行為接口的具體實現。也即,將未來易於變化和擴展的行為從類型中解構出去,分解為更為細小的接口的實現,當類型需要某種行為時只需要委托給接口的實現,由接口的實現來提供可變化的部分,這樣就不會影響類型的結構,需求改動時,只需要更改接口實現的代碼,而不需要在多個類型中修改代碼,從而達到只在一處更改卻多處受益的效果。也即,一個類型中不易變化的事物應該定義在類型中,否則提取出來定義成接口的實現。

示例代碼

namespace AppCUI
{
public interface IRun
{ void Run( ); }


public class Run : IRun { void IRun.Run( ) { Console.WriteLine( "Run!" ); } }

public class Animal
{
public string Name { get; set; }
private IRun run;
public void Run( )
{
run = new Run( ); //默認的IRun的實現
run.Run( );
}

public void ChangeRun( IRun run ) //註入其它的IRun的實現,應對今後需求的改變
{
run.Run( );
}
}

public class Tiger : Animal { }

//獅子類需要奔跑,就將奔跑接口的實現作為屬性存取,也即我需要奔跑這個行為,我委托給奔跑接口的實現為我提供奔跑的能力
//羚羊類需要奔跑,就將奔跑接口的實現作為屬性存取就可以了
//100個類需要奔跑,也同樣如此
//以後要修改奔跑的行為,只需要修改Run類的Run方法,僅此一處需要修改,不用在多個動物中修改代碼了

//如果有更特殊的奔跑行為又如何?
//只需要再定義一個SpecialRun類實現IRun就可以了!
public class SpecialRun : IRun { void IRun.Run( ) { Console.WriteLine( "SpecialRun!" ); } }

public class Programe
{
static void Main( string[] args )
{
Tiger tiger = new Tiger( );
tiger.Run( );
tiger.ChangeRun( new SpecialRun( ) );
}
}
}

  

C# - 設計模式目錄

C# - 設計模式 - 策略模式