2011-08-08 3 views
9

응용 프로그램에서 작업중인 작업 항목. 작업 항목의 상태에 따라 여러 가지 작업을 사용할 수 있습니다.디자인 패턴을 추천하십시오.

public interface IActionProvider{ 
    public void Complete(WorkItem workItem); 
    public void Cancel (WorkItem workItem); 
    public void Reassign(WorkItem workItem); 
} 

그리고 다른 세부 사항에 따라 ...

내가 현재이 같은 것을 보이는 인터페이스를 가지고 행동에 대한 기능을 제공하기 위해 ... 등 "재 할당" "취소" "완료" 작업 항목에는 인터페이스의 구체적인 구현이 있습니다. 그냥 예를 들어 ...

public class NormalActionProvider :IActionProvider 
{ 
    ... 
} 

public class UrgentActionProvider : IActionProvider 
{ 
    .... 
} 

내가 말, 새로운 액션을 추가 할 경우 문제가있다는 ... "위임"나는 인터페이스를 업데이트해야하는 과정의 모든 구현에 영향을 미친다.

열기/닫기 원칙을 위반합니까? 여기에서 나를 도울 수있는 디자인 패턴이나 리팩터링을 추천 해 주시겠습니까?

답변

11

명령 패턴이 적합 할 것 같습니다. 더 많은 명령을 수정/추가 할 수 있습니다. 명령 클래스는 주 프로그램과 분리됩니다.

public interface IActionProvider{ 
    public void execute(WorkItem item,ActionType actionType); 
} 

ActionType은 완료, 취소 & 등을 나타냅니다. 더 많은 액션 유형 & 플러그인을 적절한 명령 클래스에 계속 추가 할 수 있습니다.

0

이것은 실제로 IActionProvider으로 무엇을 달성하려 하는가에 달려 있습니다. 모든 구현이 중요한 것으로 간주하는 모든 조치를 수행 할 수 있어야하므로 실제로 구현하려는 인터페이스의 일부 여야합니다. 인터페이스는 미리 계획이 잘되어있어 지속적으로 변경할 필요가 없으면 가장 잘 작동합니다.

하지만 모든 제공 업체가 모든 조치를 구현하지 않아도되는 것 같습니다. 좋은 조언을 해 줄 수 있도록 더 자세한 정보를 알고 싶지만 한 가지 예는 일종의 이벤트 버스에 대해 공급자를 초기화하는 것입니다. 그들은 관심있는 이벤트를 구독하고 특정 구현에 적합한 이벤트에 대해서만 작업을 수행 할 수 있습니다.

3

언제든지 Decorator를 IActionProvider 인터페이스에 추가 할 수 있습니다 (Decorator design pattern을 따르십시오).

0

"는 작업 항목의 상태에 따라"국가 디자인 패턴을

한 가지 방법을 제공하거나 다른, 당신은 당신이 인터페이스 결국 클라이언트 계약을 깰 리팩토링해야합니다.

문제점을 올바르게 이해했다면 WorkItem의 상태가 에 따라 변경되는 WorkItemProcessor가 있습니다.

따라서 귀하의 WorkItemProcessor는

// Context 
    public class WorkItemProcessor 
    { 
     public IState CurrentState { get; set; } 

     public WorkItemProcessor(IState initialState) 
     { 
      CurrentState = initialState; 
     } 

     public void Process(WorkItem workItem) 
     { 
      CurrentState.Handle(this, workItem); 
     } 
    } 

그런 다음 우리가 WorkItemProcessor이 잠재적으로 WorkItem에서이

// Request 
    public class WorkItem 
    { 
     public bool CompletenessConditionHoldsTrue { get; set; } 

     public bool CancelConditionHoldsTrue { get; set; } 
    } 

이 모두 넣으려면 같은데 가정

// State Contract 
    public interface IState 
    { 
     void Handle(WorkItemProcessor processor, WorkItem item); 
    } 

    // State One 
    public class CompleteState : IState 
    { 
     public void Handle(WorkItemProcessor processor, WorkItem item) 
     { 
      processor.CurrentState = item.CompletenessConditionHoldsTrue ? (IState) this : new CancelState(); 
     } 
    } 

    // State Two 
    public class CancelState : IState 
    { 
     public void Handle(WorkItemProcessor processor, WorkItem item) 
     { 
      processor.CurrentState = item.CancelConditionHoldsTrue ? (IState) this : new CompleteState(); 
     } 
    } 

될 수 있다는 것을 여러 상태를 정의된다 함께

static void Main() 
    { 
     // Setup context in a state 
     WorkItemProcessor processor = new WorkItemProcessor(new CancelState()); 

     var workItem1 = new WorkItem { CompletenessConditionHoldsTrue = true }; 
     var workItem2 = new WorkItem { CancelConditionHoldsTrue = true }; 

     // Issue requests, which toggles state 
     processor.Process(workItem1); 
     processor.Process(workItem2); 

     Console.Read(); 
    } 

희망이 있으면 가까이 갈 수 있습니다. 건배.

0

또한 명령 패턴을 선택합니다. 개선 사항으로 추상 팩토리 메소드와 결합하여 각 명령 클래스에 대한 팩토리 클래스를 가질 수 있으며 모든 팩토리는 공통 팩토리 인터페이스를 구현합니다. 예를 들어

:

// C# 
public interface ICommand { void Execute(); } 

public interface ICommandFactory { ICommand Create(); } 

public class CommandFactoryManager 
{ 
    private IDictionary<string, ICommandFactory> factories; 

    public CommandFactoryManager() 
    { 
     factories = new Dictionary<string, ICommandFactory>(); 
    } 

    public void RegisterCommandFactory(string name, ICommandFactory factory) 
    { 
     factories[name] = factory; 
    } 

    // ... 
} 

이렇게하면 동적으로 새 명령 공장을 등록 할 수 있습니다. 예를 들어 런타임에 DLL을로드하고 리플렉션을 사용하여 ICommandFactory 인터페이스를 구현하는 모든 클래스를 가져올 수 있으며 간단한 플러그인 시스템을 사용할 수 있습니다.