+처음 상태와 다음 상태는 누가 정하는가
새 문서는 아직 제출되지 않았으므로 초안에서 시작한다. 코드의 private DocumentState state = new DraftState(null);가 문서마다 처음 사용할 상태 객체를 만든다. 여기서 null은 상태가 없다는 뜻이 아니라, 처음 초안에는 반려 사유가 없다는 뜻이다.
DocumentState는 상태들이 공통으로 받는 요청의 형태를 정의하고, state 필드는 지금 그 요청을 처리할 객체 하나를 가리킨다. 처음에는 실제 객체가 DraftState이므로 문서의 Submit()도 초안 상태의 구현으로 전달된다.
다음 상태는 메서드가 처리한 사건에 따라 정한다. 호출자가 Submit()을 요청하면 DraftState.Submit()이 document.state = new InReviewState();를 실행하고, 그다음 요청부터는 새 검토 상태가 처리한다. 승인할 때는 InReviewState.Approve()가 PublishedState로, 반려할 때는 InReviewState.Reject(reason)이 사유를 가진 DraftState로 교체한다. 시간이 지났다고 상태가 저절로 바뀌는 것은 아니다.
Stage 값도 따로 대입하지 않는다. Stage => state.Stage가 현재 객체의 값을 읽으므로 상태 객체를 교체하면 조회 결과도 함께 바뀐다. 외부에는 state를 임의로 바꾸는 setter를 열지 않고, 허용한 요청을 통해서만 전이하게 했다. 저장된 문서를 불러와 상태를 복원하는 기능은 이 예제에 포함하지 않는다.