2012-11-22 2 views
1

게시 된 질문 here을 참조하면, 상속이 아닌 합성을 사용하여 클래스를 확장하기위한 선택적인 동작을 해결하는 좋은 방법이라면 의견을 말씀해주십시오. Plannable 행동은 전략 패턴에 의해 확장됩니다.더미 콘크리트 전략을 사용한 전략 패턴

그래서 Task 클래스는 선택적으로 다양한 동작의 조합을 가질 수 있습니다. Plannable은 그 중 하나 일 뿐이므로 상속은 분명히 여기에서 의미가 없습니다.

질문에는 작업에 특정 동작이없는 경우 어떻게해야합니까? 나는 몇 가지 가능한 방법을 참조하십시오 각 작업에 대한

  1. 인스턴스화 구체적인 전략을, 그리고 TaskPlannable하지 않을 때 (이 대안은 다음과 같습니다) "더미"전략을 구현합니다. 모든 코드를 통해 이상한 널 (NULL) StartFinish 변수는 경우 작업에 nullable IPlanningStrategy 변수를 갖는
  2. 계획, 그리고 그것은 "승진"경우에만 구체적인 전략으로 인스턴스화되지 않습니다 ...이 경우가있다 할 수 Plannable. 여기 ** ** 문제가 매우 중요
    public class Task 
    { 
        public string Title { get; set; } 
    
        private IPlanningStrategy planningStrategy; 
    
        public Task() 
        { 
         planningStrategy = new NoPlanStrategy(); 
        } 
    
        public Task(IPlanningStrategy initialPlanningStrategy) 
        { 
         planningStrategy = initialPlanningStrategy; 
        } 
    
        public void SetPlanningStrategy(IPlanningStrategy newPlanningStrategy) 
        { 
         planningStrategy = newPlanningStrategy; 
        } 
    
        public DateTime? Start { get { return planningStrategy.Start; } } 
        public DateTime? Finish { get { return planningStrategy.Finish; } } 
    } 
    
    
    public interface IPlanningStrategy 
    { 
        public void CalculatePlan(); 
        public DateTime? Start { get; } 
        public DateTime? Finish { get; } 
    } 
    
    // "Dummy" strategy, used when Task does not have Planning behaviour 
    // 
    public class NoPlanStrategy : IPlanningStrategy 
    { 
        public void CalculatePlan() { } 
        public DateTime? Start { get { return null; } } 
        public DateTime? Finish { get { return null; } } 
    } 
    
    
    
    public class PlanStrategyA : IPlanningStrategy 
    { 
        private int parameter1; 
        private int parameter2; 
        private DateTime? start; 
        private DateTime? finish; 
    
        public PlanStrategyA(int p1, int p2) 
        { 
         parameter1 = p1; 
         parameter2 = p2; 
         start = finish = null; 
        } 
    
        public void CalculatePlan() 
        { 
         // ... uses parameter1 & parameter2 
         // ... to calculate start and finish 
        } 
    
        public DateTime? Start { get { return start; } } 
    
        public DateTime? Finish { get { return finish; } } 
    } 
    
    public class PlanStrategyB : IPlanningStrategy 
    { 
        public int parameter3; 
    
        // ... the rest is similar to PlanningStrategyA 
    
    } 
    

    가 지금은 다른 참조 :

대안 (1) 같은 것을해야한다. 각각의 구체적인 Strategy 클래스는 알고리즘 옆에 있으며, 물론이 알고리즘을 구현하는 모든 작업, 특정 매개 변수에 속하는 추가 매개 변수 (Task에만 해당)에 대해 공유됩니다.

당신이 상상할 수있는 parameter1Effort로 (또는, 말, 작업을 완료하는 데 필요한 나머지 시간 수), 및 parameter2LastDate이라고한다 (즉, 제약 날짜를 나타내는. 마지막으로 허용 가능한 날짜는 작업을 완료합니다). 이 매개 변수는 당연히 특정 Task에 속하지만이 매개 변수를 구현하는 경우에만 StrategyA입니다.

Task 클래스 외부의 인스턴스화 전략이 맞지 않는 것 같습니다. 또는이 방법을 일부 Factory 작업해야합니까?

답변

0

IMO Task 클래스에 너무 많은 정보를 노출하고 있습니다. 다음과 같이 내가 할 것 :

public class Task 
{ 
    // what is title being used for? 
    public string Title { get; set; } 

    private IPlanningStrategy planningStrategy; 

    public Task(IPlanningStrategy initialPlanningStrategy) 
    { 
     // Initialize it outside of constructor 
     if(initialPlanningStrategy == null) 
     { 
      throw new NullArgumentException(); // or return. 
     } 
     planningStrategy = initialPlanningStrategy; 
    } 

    public void CalculatePlan(){ 
     // check null and return. 
     planningStrategy.CalculatePlan(); 
    } 

} 

클라이언트 야해 시작 알고, 마무리, 내가 알고리즘의 컨테이너의 책임으로 것을 볼니까.

또한 NoPlanStrategy에서 아무 것도하지 않으면 왜 소개해야합니까? 제거.

+0

답변 해 주셔서 감사합니다. Null을 허용하는'Task.planninStrategy'를 가지고 있다면 물론, "더미"'NoStrategy' 클래스가 필요없고 제거 될 수 있습니다. 두 번째 요점에 대해서, 내 고객은 '시작'과 '마침'에 대해 정말로 관심이 있습니다. 왜냐하면 전체 계획 동작은 모두 '시작'과 '마침', 즉 '작업'이 '계획 가능'이면 전부 보여주기 때문입니다. 그러나 다시,'Start'와'Finish'는'Task.CalculatePlan()'과 비슷한 방식으로 표현 될 수 있습니다. null이 아닌지 검사하고'Start/Finish'를 반환합니다. – buggy08

+0

예. 그렇게 할 수 있습니다. 시작/완료를 객체에 넣어야하는 경우, 클라이언트가이 계약을 만족시키기 위해 기대하는 정보를 반환하도록 ur 인터페이스를 변경하십시오. 그에 따라 예외를 처리하십시오. – DarthVader

+0

여기에 더 많은 문제가 있습니다 :-) 나는 방금 질문을 확장했습니다 ... – buggy08