2014-02-19 1 views
0

분리하기 :주 패턴 : 나는 다음과 같은 StackOverflow의 게시물에서 도움의 비트와 상태 패턴을 구현에서 이동을 했어 MoveNext는() 메소드

state pattern

좋은 지금까지. 지금 (다음 상태로 인정의를 문서.) 객체를 이동할 수 있습니다

public override void MoveNext(Document currDoc, IProcessor currProcessor) 
    {        
     TransitionTo<ACKNOWLEDGED>(() => new ACKNOWLEDGED(_factory, _context)); 
     currProcessor.LogTheChange(currDoc); 
     currProcessor.DoSomethingElse(currDoc) 
    } 

지금 상태를 변경하는 과정에서, 나는 다른 클래스에서 다른 작업을 수행 할. 주와 IP 프로세서를 연결하는 것이 좋습니다.

나는 국가가 2 개의 신중한 국가 (이 경우에는 UNACKNOWLEDGED와 ACKNOWLLEDGED) 사이의 변경에만 관심을 가져야한다고 생각합니다.

기본 객체에 대한 실제 업데이트는 어떻게 발생합니까? 내가 알 수있는 한, 문서 객체를 moveNext() 메소드에 전달하여 다른 곳으로 전달할 수 있습니다. 올바르지 않으면 IProcessor가 처리 할 이벤트를 발생시켜야한다면 내 상태 개체가 어떻게 분리 된 방식으로 IProcessor와 통신해야합니까? 또는 MoveNext() 메서드에서 인터페이스를 인수로 전달해야합니까? 나는 의심하지 않는다.

+0

상태가 해당 게시물에 표시된 선형 방식으로 움직이기 때문에 해당 게시물과 "MoveNext"패러다임을 사용 하시겠습니까? 제 경험상 많은 주 기계가 상태 전환에 분기 또는주기를 가지고 있습니다. – tcarvin

+0

hiya, 네, 선형으로 움직입니다. 더 이상 복잡하지 않아도됩니다 .. 내가 가지고있는 문제는이 특정 moveNext() 메소드가 현재 a) currDoc b) IProcessor와 결합되어 있다는 것입니다. –

+0

IProcessor 란 무엇이며 어디에서 왔습니까? – tcarvin

답변

0

흠. 흥미로운 문제는 내가 이것을 말할 것입니다. 상태 전환이 오직 하나의 효과 (IProcessor가 무언가 또는 몇 가지 일을하도록 만드는 효과)를 갖는다면, 그 방법은 아마도 그럴 것입니다.

상태 변경의 결과로 많은 일이 발생할 수 있지만 MoveNext() 함수가이 변경이 유발되는 유일한 방법 인 경우에도 더 많은 프로세서와 동작을 방법. 프로세서 중 하나가 예외를 throw하면 결국 어떤 일이 발생할지 걱정해야 할 수도 있습니다.

그러나 상태 변경이 여러 위치 (MoveNext()와 같은 많은 함수)에서 시작될 수 있거나 상태가 조건에 따라 변경 될 수있는 경우 상태 변경을 감시하는 엔터티가 있어야합니다. 일종의 게시 및 구독 메커니즘을 사용하여 이것을 사용할 수 있습니다. 또는 단순히 주체가 메시지를 방출 할 때 특정 객체가 관측하는 관습에 따라 사용할 수도 있습니다.

저라면, 저는 아마도 내 상태 객체를 spring.net 이벤트 시스템 (http://springframework.net/doc-latest/reference/html/quickstarts.html)과 같은 것으로 연결할 것입니다. 그러나, 아마도 스프링을 포함하지 않는 .net에서 이것을하는 다른 방법이있을 것입니다.

+0

hiya Robert, 답장을 보내 주셔서 감사합니다. MoveNext() 메서드 만이 chage가 시작되는 유일한 시점이므로 현재 구현할 것입니다. –

0

상태 패턴을 사용하는 클래스의 호출자가 상태 시스템이 있음을 알고 있어야한다고 생각하지 않습니다. 따라서 나는 Documemt.MoveNext을 호출하는 클라이언트 코드의 팬이 아니다. 많은 구현 세부 사항을 보여줍니다.

다음은 Document 클래스 내에서 상태 패턴을 숨기는 대체 구현입니다. 각 상태 하위 클래스를 사용하여 Document 멤버에 대한 모든 액세스 권한을 제공하는 동안 개인 내부 클래스를 사용하여 상태 시스템의 세부 정보를 완전히 숨길 수 있습니다. Document 클래스 파일의 코드 난이도를 피하기 위해 여전히 내부 클래스를 자체 코드 파일에 보관합니다.

Document.cs

partial class Document 
{ 

    public Document() 
    { 
     // default/starting state 
     this.TransitionToState<EmptyState>(); 
    } 

    // misc data for example 
    public int? caseNumber { get; private set;} 
    public DateTime? WhenSubmitted { get; private set; } 
    public DateTime? WhenAcknowlegded { get; private set; } 
    public int? CompletionStatus { get; private set; } 

    // transitions: EMPTY -> ASSIGNED -> UNACKNOWLEDGED -> ACKNOWLEDGED -> COMPLETED 
    private DocumentState State { get; set; } 


    // state-related methods are forwarded to the current DocumentState instance 

    public void AssignCase(int caseNumber) 
    { 
     State.AssignCase(caseNumber); 
    } 

    public void SubmitTo(object clientInfo) 
    { 
     State.SubmitTo(clientInfo); 
    } 

    public void Acknowledged(object ackInfo) 
    { 
     State.Acknowledged(ackInfo); 
    } 

    public void Complete(int statusCode)   
    { 
     State.Complete(statusCode); 
    } 

    // events could be used for this callback as well, but using private inner 
    // classes calling a private member is probably the simplest. 

    private void TransitionToState<T>() where T : DocumentState, new() 
    { 
     // save prior for a moment 
     DocumentState priorState = State; 

     // this can be lookup from map instead of new() if you need to keep them 
     // alive for some reason. I personally like flyweight states. 
     DocumentState nextState = new T(); 

     // activate the new state. it will get notified so it can do any one- 
     // time setup 
     State = nextState; 
     State.EnterState(this); 

     // let the prior state know as well, so it can cleanup if needed 
     if (priorState != null) 
      priorState.ExitState(); 

    }   

} 

DocumentState.

partial class Document 
{ 

    // Represents an empty document waiting to get assigned a case #. Once 
    // that is satisfied, it performs its logic and triggers a state 
    // transition to the next state. 
    class EmptyState : DocumentState 
    { 
     protected override void OnAssignCase(int caseNumber) 
     { 
      // business logic 
      Context.caseNumber = caseNumber; 
      // write to log 
      // etc, etc 

      // goto next state 
      Context.TransitionToState<AssignedState>(); 
     } 
    } 

} 

partial class Document 
{ 

    // Represents an document assigned a ase number but not submitted to a 
    // client yet. Once that happens it performs its logic and the triggers a state 
    // transition. 
    class AssignedState : DocumentState 
    { 
     protected override void OnSubmitTo(object clientInfo) 
     { 
      // business logic 
      Context.WhenSubmitted = DateTime.Now; 
      // etc 
      // etc 

      // goto next state 
      Context.TransitionToState<UnacknowledgedState>(); 
     } 
    } 
} 

partial class Document 
{   
    // you get the idea by now... 
    class UnacknowledgedState : DocumentState 
    { 
     protected override void OnAcknowledged(object ackInfo) 
     { 
      // business logic 
      Context.WhenAcknowlegded = DateTime.Now; 

      // goto next state 
      Context.TransitionToState<AcknowledgedState>(); 

     } 
    } 
} 

partial class Document 
{ 
    class AcknowledgedState : DocumentState 
    { 
     protected override void OnComplete(int statusCode) 
     { 
      Context.CompletionStatus = statusCode; 

      Context.TransitionToState<CompletedState>(); 
     } 

    } 
} 

partial class Document 
{ 
    class CompletedState : DocumentState 
    { 
     // note there are no methods overriden. this is the last state. 
    } 
} 

그리고 마지막으로, Program.cs :

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.ReadLine(); 

     Document doc = new Document(); 

     Console.ReadLine(); 

     doc.AssignCase(123456); 

     Console.ReadLine(); 

     doc.SubmitTo("clientAddress"); 

     Console.ReadLine(); 

     doc.Acknowledged("responseFromClient"); 

     Console.ReadLine(); 

     const int TERMS_REJECTED = 123; 
     doc.Complete(TERMS_REJECTED); 

     Console.ReadLine(); 

    } 
} 

당신이 어떤 질문이 있으면 알려주세요 CS

partial class Document 
{ 

    abstract class DocumentState 
    { 

     //-------------------------------------------- 
     // state machine infrastructure 
     //-------------------------------------------- 

     public void EnterState(Document context) 
     { 
      this.Context = context; 
      Console.WriteLine("Entering state: " + this.GetType().Name); // debug only 
      OnEnterState(); 
     } 

     public void ExitState() 
     { 
      this.Context = null; 
      OnExitState(); 
      Console.WriteLine("State that was exited: " + this.GetType().Name); // debug only 
     } 

     protected Document Context { get; private set; } 

     //-------------------------------------------- 
     // a mirror of the document-manipulation methods that concerns states 
     //-------------------------------------------- 

     public void AssignCase(int caseNumber) 
     { 
      OnAssignCase(caseNumber); 
     } 

     public void SubmitTo(object clientInfo) 
     { 
      OnSubmitTo(clientInfo); 
     } 

     public void Acknowledged(object ackInfo) 
     { 
      OnAcknowledged(ackInfo); 
     } 

     public void Complete(int statusCode) 
     { 
      OnComplete(statusCode); 
     } 

     //-------------------------------------------- 
     // state subclasses override the methods they need. Typically not 
     // all are needed by all states. Default implementation is to 
     // throw an exception if a state receives and "unexpected" invocation. 
     //-------------------------------------------- 

     protected virtual void OnAssignCase(int caseNumber) 
     { 
      throw new InvalidOperationException(); 
     } 

     protected virtual void OnSubmitTo(object clientInfo) 
     { 
      throw new InvalidOperationException(); 
     } 

     protected virtual void OnAcknowledged(object ackInfo) 
     { 
      throw new InvalidOperationException(); 
     } 

     protected virtual void OnComplete(int statusCode) 
     { 
      throw new InvalidOperationException(); 
     } 

     //-------------------------------------------- 
     // additional hooks that can be override if needed that signal the 
     // enter and exit of the state. 
     //-------------------------------------------- 

     protected virtual void OnEnterState() 
     { 
     } 

     protected virtual void OnExitState() 
     { 
     } 

    } 

} 

상태 클래스 (I는 설명을 추가 사람을 추가) .

관련 문제