次の画像では、State Patternの Appliing Domain-Driven Design and Patterns:With Examples in C#)および.NET
SalesOrder
エンティティをデータベースに永続化しようとしています。通常、データベースにはsalesOrder
テーブルがあり、フィールドcurrentState
はエンティティの現在の状態を示しています。
singleエンティティがあり、その状態には異なる動作しか含まれていないため、この実装は問題ありません。
ただし、異なる状態の他のプロパティを追跡する必要がある場合はどうなりますか?例:
quantity
、cancellationReason
、cancelledBy
、cancellationDate
を追跡する必要があります。refundQuantity
、refundPrice
、refundFee
を追跡する必要があります。つまり、基本的には、CancelledSalesOrder
エンティティとRefundedSalesOrder
エンティティに追加の属性があるようです。他の州についても同じことが言えます。
だから今の私の問題は、デザインを状態パターンの使用から継承の使用に変更しなければならないことです。ただし、継承では、実行時に状態を動的に変更できません(状態図が最初に解決する問題)。
だから私の質問:
いいえ、状態パターンは失敗しません。追加の「キャンセル」属性を「キャンセル済み」状態の一部にして、追加の「払い戻し」属性を「返金済み」状態の一部にしてください(図で後者の状態を忘れてしまったと思いますか?)
「状態」エンティティはSalesOrder
の集合体であるため、「状態」の属性はSalesOrder
への「詳細の追加」としてのみ見ることができます。
OrderState
階層にどの種類の継承マッピングを選択するかは、実際には問題になりません。通常の3つはどれでも機能します。
状態パターンを使用すると、後で状態が変化した場合でも、以前の状態の属性を保持できます。たとえば、状態が「発送済み」から「請求済み」に変わっても、「配送先住所」を保持する必要がある場合があります。これは、一度に複数の状態を許可することで解決できます。SalesOrderとOrderStateの関係を「1:1」ではなく「1:n」にするだけです。したがって、「状態を出荷済みから請求済みに変更する」のではなく、「請求済み」の状態を事前に削除せずに、「請求済み」という追加の状態を「StateOrder」エンティティに追加します。もちろん、このモデルを使用して、発送されるすべての注文を探す場合、「付与」された注文だけでなく、「付与されたがまだ発送されていない注文」もチェックする必要があります。ただし、これは処理の詳細にすぎず、処理が難しくなりすぎてはなりません。
複数の状態を持つことは、実際の状況をより適切に反映するので、IMHOは「より良い」モデルです。たとえば、発送して請求したものは、「請求済みおよび出荷済み」ではなく、「出荷済みおよび請求済み」です。