我知道標題很奇怪,所以讓我試着做一些基本的設置。「嵌套」/組合策略模式?
我有一個叫做StyleBundle的對象。基於兩件事情,StyleBundle的持續時間和StyleBundle(Unlimited或PerStyle)的「類型」將決定StyleBundle的整體價格。所以,這裏快速剪下了StyleBundle:
public class StyleBundle
{
public decimal Price {get; set;}
public StyleType Type {get; set;} //STyleType is a simple enum, either "Unlimited" or "PerStyle"
public Duration Duration {get; set;}
}
這是持續時間。基本上,它有一個枚舉類型,是DurationType,它可以像DurationType.OneYear,DurationType.TwoYears等值...
public class Duration
{
public Duration(TimeSpan timeSpan, string name, DurationType type)
{
this.TimeSpan = timeSpan;
this.Name = name;
this.Type = type;
}
public TimeSpan TimeSpan { get; set; }
public string Name { get; set; }
public DurationType Type { get; set; }
}
在我StyleBundle類,我通過持續的戰略工廠叫StyleBundlePricingStrategy。下面是類:返回
public class StyleBundlePricingFactory
{
public static IPricingStrategy GetPricing(Duration duration)
{
if (duration.Type == DurationType.OneYear) { return new OneYearPricingStrategy(); }
if (duration.Type == DurationType.TwoYear) { return new TwoYearPricingStrategy(); }
etc...
etc...
}
}
類實現IPricingStrategy接口:
public interface IPricingStrategy
{
decimal GetPriceFor(StyleBundle aStyleBundle);
}
它得到的價格爲StyleBundle。每個策略類都封裝了給定DurationType的價格檢索方式。下面是OneYearPricingStrategy類的一個示例:
public class OneYearPricingStrategy : IPricingStrategy
{
public decimal GetPriceFor(StyleBundle aStyleBundle)
{
if (aStyleBundle.StylePricingType == StylePricingType.PerStyle)
{
return aStyleBundle.Products.Count() * 2500m;
}
else
{
return 50000m;
}
}
}
好吧,非常基本的策略設置。
是在吃了我的事情是,如果你看一下這行代碼中的「OneYearPricingStrategy」類:
if (aStyleBundle.StylePricingType == StylePricingType.PerStyle)
,你會看到,我還是有使用條件的策略類以說明StyleBundle類型。 StyleBundle的類型將影響價格的計算方式。
對我來說,這是不好的設計,我寫的每個策略類的B/C「OneYearPricingStratety」,「TwoYearPricingStrategy」等... StylePricingType條件被複制並粘貼到所有的Strategy類。
這不好,b/c當我不得不添加一個新的StylePricingType時會發生什麼?我將不得不重新進入每個PricingStrategy類並更新代碼,所以將整個SRP排除在外(與其他事情一起)...
我需要的是一種實現某種類型模式的方法這將允許我結合兩個「stratagies」(持續時間與StyleBundleType),並允許規則生活在一個地方......不要在代碼中散佈。
當您爲一個策略實施時,很容易消化戰略模式,但這是兩個組合,而且我知道現在編寫它的方式不是一種好的做法,並且不能完成我想要它。
也許這是錯誤的模式?
任何指針將不勝感激。
謝謝, 邁克
編輯:
在反應亭子間的答案,我想提供我是如何走到擺在首位的策略模式的一些更詳細。我並沒有首先將實施策略強加於策略,但看到了我認爲的代碼味道,並決定策略模式可以幫助我。
最初,使用StyleBundle.Price屬性看起來像這樣:
public decimal Price
{
get
{
if (this.StylePricingType == StylePricingType.PerStyle)
{
if (this.Duration.Type == DurationType.ThreeDays)
{
_price = 1500m;
}
else if (this.Duration.Type == DurationType.OneYear)
{
_price = 2500m;
}
else if (this.Duration.Type == DurationType.TwoYears)
{
_price = 2000m;
}
else if (this.Duration.Type == DurationType.ThreeYears)
{
_price = 1650m;
}
}
else if (this.StylePricingType == StylePricingType.Unlimited)
{
if (this.Duration.Type == DurationType.ThreeDays)
{
throw new Exception("You can not have a StyleBundle of type Unlimited for a Duration of three days.");
}
else if (this.Duration.Type == DurationType.OneYear)
{
_price = 50000m;
}
else if (this.Duration.Type == DurationType.TwoYears)
{
_price = 40000m;
}
else if (this.Duration.Type == DurationType.ThreeYears)
{
_price = 33500m;
}
}
else
{
throw new Exception("Illegal StylePricingType passed to Product.");
}
return _price;
}
private set
{
_price = value;
}
}
我看到了任何時候,我會添加其他時間類型,我需要進入StyleBundle和更改代碼...到我認爲這似乎是激勵原則,足以尋求更好的解決方案。現在
,與戰略設計模式這個問題的應用程序,我StyleBundle.Price屬性看起來是這樣的:
public decimal Price
{
get
{
return _pricingStrategy.GetPriceFor(this);
}
private set
{
_price = value;
}
}
其中_pricingStrategy是IPricingStrategy,並決定其實現者了新的決定通過在StyleBundle的構造函數中調用StyleBundlePricingFactory.GetPricing(duration)類。
Garret,請參閱我的編輯。我最初的代碼是「臭」,這裏策略模式的應用似乎對我有意義。 – 2011-12-15 20:21:56