상태 패턴을 사용하는 클래스의 호출자가 상태 시스템이 있음을 알고 있어야한다고 생각하지 않습니다. 따라서 나는 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는 설명을 추가 사람을 추가) .
상태가 해당 게시물에 표시된 선형 방식으로 움직이기 때문에 해당 게시물과 "MoveNext"패러다임을 사용 하시겠습니까? 제 경험상 많은 주 기계가 상태 전환에 분기 또는주기를 가지고 있습니다. – tcarvin
hiya, 네, 선형으로 움직입니다. 더 이상 복잡하지 않아도됩니다 .. 내가 가지고있는 문제는이 특정 moveNext() 메소드가 현재 a) currDoc b) IProcessor와 결합되어 있다는 것입니다. –
IProcessor 란 무엇이며 어디에서 왔습니까? – tcarvin