제목이 이상하다는 것을 알고 있으므로 기본 설정을 해보겠습니다."중첩 된"/ 결합 된 전략 패턴?
저는 StyleBundle이라는 객체를 가지고 있습니다. StyleBundle의 Duration과 StyleBundle (Unlimited 또는 PerStyle)의 "type"의 두 가지 사항에 따라 StyleBundle의 전체 Price가 결정됩니다. 여기에 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;}
}
여기에 재생 시간이 있습니다. 기본적으로, 내가 StyleBundlePricingStrategy라는 전략 공장에 시간을 통과 등 DurationType.OneYear, DurationType.TwoYears, 같은 값이 될 수 DurationType입니다 열거, ... 내 StyleBundle 클래스에서
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의 가격을 얻을 수
public interface IPricingStrategy
{
decimal GetPriceFor(StyleBundle aStyleBundle);
}
:
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 인터페이스를 구현 반환. 각 전략 클래스는 지정된 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 유형은 가격 계산 방법에 영향을 미칩니다.
저에게 이것은 "OneYearPricingStratety", "TwoYearPricingStrategy"등으로 작성한 각 전략 클래스의 나쁜 디자인입니다. StylePricingType 조건부가 복사되어 모든 전략 클래스에 붙여 넣어집니다.
이것은 좋지 않습니다. b/c 새로운 StylePricingType을 추가해야 할 때 어떻게됩니까? 각 PricingStrategy 클래스로 돌아가서 코드를 업데이트해야하므로 (다른 것들과 함께) 전체 SRP가 창 밖으로 나옵니다 ...
내가 필요한 것은 어떤 유형의 패턴을 구현하는 것입니다. 그러면 두 개의 "전략"(Duration과 StyleBundleType)을 결합하고 규칙을 한 곳에서 살릴 수 있습니다. 코드를 넘어서게하지 마십시오.
하나의 전략을 구현할 때 STrategy 패턴을 쉽게 소화 할 수 있지만이 두 가지를 조합 한 것이므로 지금 작성한 방식을 알고 있으며 좋은 연습은 아니며 그것을 원한다.
어쩌면 잘못된 패턴일까요?
모든 포인터가 감사 할 것입니다.
감사합니다, 마이크
편집 : 다락방의 대답에 반응
이, 내가 처음에 전략 패턴에 도착 방법에 대한 자세한 내용을 제공합니다. 먼저 전략을 구현하기보다는 코드 냄새라고 생각하고 전략 패턴이 도움이 될 수 있다고 판단했습니다.
처음에는 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 속성은 다음과 같습니다
는 _pricingStrategy이 IPricingStrategy하고 결정이다public decimal Price
{
get
{
return _pricingStrategy.GetPriceFor(this);
}
private set
{
_price = value;
}
}
최대 새에있는 구현의 결정 StyleBundle의 생성자에서 StyleBundlePricingFactory.GetPricing (duration) 클래스를 호출하면됩니다.
가렛, 제 편집을 참조하십시오. 나의 초기 코드는 "냄새 나는"것이었고, 여기서 전략 패턴을 적용하는 것이 나에게 의미가있는 것처럼 보였다. –
알았어, 내 업데이트 된 답변을 참조하십시오. –