単純な列挙を使用して、エンティティの状態を表すことがよくあります。問題は、主に状態に依存する動作、または状態遷移が特定のビジネスルールに従わなければならない動作を導入するときに発生します。ステートパターンとドメイン駆動デザイン
は(その状態を表すために列挙を使用しています)、次の例を見てみましょう:
public class Vacancy {
private VacancyState currentState;
public void Approve() {
if (CanBeApproved()) {
currentState.Approve();
}
}
public bool CanBeApproved() {
return currentState == VacancyState.Unapproved
|| currentState == VacancyState.Removed
}
private enum VacancyState {
Unapproved,
Approved,
Rejected,
Completed,
Removed
}
}
あなたはこのクラスはすぐに我々は完全拒否のための方法を、追加として、非常に冗長になることを見ることができ、削除など
代わりに、私たちは私たちがオブジェクトとしてそれぞれの状態をカプセル化することを可能にする状態パターン、導入することができます:これはbetweeの移行が容易になり
public abstract class VacancyState {
protected Vacancy vacancy;
public VacancyState(Vacancy vacancy) {
this.vacancy = vacancy;
}
public abstract void Approve();
// public abstract void Unapprove();
// public abstract void Reject();
// etc.
public virtual bool CanApprove() {
return false;
}
}
public abstract class UnapprovedState : VacancyState {
public UnapprovedState(vacancy) : base(vacancy) { }
public override void Approve() {
vacancy.State = new ApprovedState(vacancy);
}
public override bool CanApprove() {
return true;
}
}
をn個の状態は、現在の状態に基づいてロジックを実行するか、我々がする必要がある場合は、新しい状態を追加します。このカプセル化は、クリーナーようだが十分な状態を与え
// transition state
vacancy.State.Approve();
// conditional
model.ShowRejectButton = vacancy.State.CanReject();
、これらはあまりにも非常に冗長になることができます。私はGreg Young's post on State Pattern Misuseを読んでいます。代わりにポリモルフィズムを使用しています(私はApprovedVacancy、UnapprovedVacancyなどのクラスを持っています)。しかし、これがどう役立つか分かりません。
このような状態遷移をドメインサービスに委任するか、この状態でStateパターンを使用するのは正しいですか?
消費者が状態を直接変更してはならない場合、これは私のエンティティの各状態遷移のためのメソッドで終わることを意味します。では、私はここで本当に何を得ているのですか? –
あなたはカプセル化され、if文の束が存在しない:)公式の利点は次のとおりです。1.状態別の振る舞いと異なる状態の振る舞いをローカライズします。 2.状態遷移を明示します。 3.状態オブジェクトを共有することができます。 –
ありがとうございます。最終的な質問の1つとして、Vacancyをドキュメントストア(RavenDB)に保存しています。関連する状態オブジェクトをロードするか、状態オブジェクト全体を格納するために使用される列挙型を永続化することを提案してください –