Я знаю, что название странное, поэтому позвольте мне попытаться выполнить некоторые базовые настройки.
У меня есть объект с именем StyleBundle.На основе двух вещей, Duration of 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 я передаю Duration фабрике стратегий с именем 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)
вы увидите, что мне все еще нужно использовать условное выражениев классе Strategy для учета типа StyleBundle.Тип StyleBundle будет влиять на то, как рассчитывается цена.
Для меня это плохой дизайн, б / к для каждого класса стратегии я пишу "OneYearPricingStratety", "TwoYearPricingStrategy" и т. Д. ... условно StylePricingTypeКопируется и вставляется во все классы Стратегии.
Это не хорошо, что происходит, когда мне нужно добавить новый StylePricingType?Мне придется вернуться к каждому классу PricingStrategy и обновить код, чтобы в окне выводился весь SRP (наряду с другими вещами) ...
мне нужен способ реализации некоторого типапаттерна, который позволит мне объединить две «стратагии» (Duration с 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;
}
}
Я видел, что всякий раз, когда я добавляю другой тип Duration, мне нужно заходить в StyleBundle и менять код ... для меня, это казалось достаточно мотивирующим принципом, чтобы искать лучшее решение.
Теперь, с применением шаблона проектирования Стратегии к этой проблеме, мое свойство StyleBundle.Price выглядит следующим образом:
public decimal Price
{
get
{
return _pricingStrategy.GetPriceFor(this);
}
private set
{
_price = value;
}
}
, где _pricingStrategy - это IPricingStrategy, и решение о том, какой разработчик использовать для нового -решено путем вызова класса StyleBundlePricingFactory.GetPricing (duration) в конструкторе StyleBundle.