2009-04-14 9 views
4

私は一連の定義された状態を経るOrderクラスを持っています。これを助けるために、OrderオブジェクトにIOrderStateインターフェイスを実装するCurrentStateメンバがあるようなStateパターンを実装しました。私はその後、OrderStateNew、OrderStateDeliveredなどのこのインターフェイスの具体的な実装を持っています状態パターンを使用するオブジェクトは、次の状態にどのように移行する必要がありますか?

私の質問は、状態間のOrderオブジェクトを移行する正しい方法は何ですか?外部サービスが状態を設定できるようにするOrder.SetState()メソッドを持つことは容認できますか?状態の変化を決定する基準はOrderオブジェクトの外部に格納されているので、これは明らかな答えですが、私のオブジェクトにpublicメソッドを持たせることで、このような基本的なものを変更するのは少し不安です。

追加の明確化 私は、私が実際に最初の場所で正しくパターンを使用している場合、私は疑問に思うので、私の実装に関するいくつかの詳細を追加すると便利かもしれないと思いました。ここでオーダーを作成し、認可するためのpulbic APIが

Dim orderFacade As New OrderFacade 
Dim order = orderFacade.createFrom(customer) 

' Add lines etc 

' This will validate the order and transition it to status 'Authorised' 
Dim valid = orderFacade.Authorise(order) 

' This will commit the order, but only if it is at status 'Authorised' 
Dim result = orderFacade.Commit() 

OrderFacade.Authorise()関数は、あなたが見ることができるように、この

Public Function Authorise(ByRef originalOrder As Order) As ValidationSummary 

    If originalOrder.CurrentState.CanAuthorise() Then 

     Dim validator = OrderValidatorFactory.createFrom(originalOrder) 
     Dim valid = validator.ValidateOrder(originalOrder) 

     If valid.IsValid Then 
      originalOrder.SetOrderStatus(OrderStatus.Authorised) 
     End If 

    Return valid 

    End If 

End Function 

ようになりますです、currentStateのメンバーが決定し、現在のIOrderState実装ですどのアクティビティがオブジェクトに対して有効であるかを示します。私はこれがOrderFacadeではなく移行を決定する責任があるべきかどうか疑問に思いますか?

+0

関連:http://stackoverflow.com/questions/1647631/c-state-machine-design – jldupont

答えて

3

割り当てではなく含意によって状態を変更することを検討してください。

私が今までに見たほとんどの場合、州は他のプロパティから推測できます(うまくいけばクラス内)。そうであれば、状態を保持しないでください。必要に応じて状態を引き出します。さもなければ、推論された値と割り当てられた値との間に問題のある不一致が生じることがよくあります。 (そして、私の経験では、常に右である「派生」。)

(複雑さは、多くの場合、クラスのトランザクションログを確認し、最新のイベント(複数可)を考慮することである。しかし、それはとにかくそれ価値がある。)

1

たとえば、非公開にパッケージ化するメソッドの可視性を減らすことができます。あなたのケースでは、これが唯一の方法だと思います。つまり、状態マシンを実装する親抽象クラスを持ち、nextState(inputParameter)メソッドのグループを持っていて、その状態を対応する状態に移します。

1

「正しい」答えはないと思います。あなたのステートマシン用に選択したアーキテクチャに本当に依存しています。状態を変更するためのすべてのロジックがOrderクラス内にカプセル化されていれば、SetStateメソッドを公開することは貧弱な習慣になると思います。しかし、Orderクラスの外に状態決定ロジックをすでに配置しているので、パブリックなSetStateメソッドなどを公開することが適切である(必要である)ようです。

もちろん、状態決定ロジックをOrderクラスに移すこともできますが、投稿した内容に基づいて非常に複雑なクラスが作成されるようです。

とにかく、単純に言えば、コードはハードとファーストのルールを設定するのではなく、コードを設計するのに役立ちます。アーキテクチャにパターンを適用するのは、アーキテクトにパターンを適用するのではなく、最適な方法でパターンを適用することです。

2

SetState()メソッドは、さらに状態を変更してオーダーを拡張することに利点があります。しかし、私はそれをお勧めしません。 State patternは、ステートフルなインターフェイスを他のクラスに提示する方法ではなく、別のクラスの異なるステートに固有の動作を収集することに関するものです。

ご注文の場合、確認、了解通知、出荷通知、出荷、請求書& cなど自然に発生するビジネスイベントについて考え、それらの周囲に明示的なインターフェイスを設計してください。インターフェイスをどのように設計するかは、アプリケーションロジックがどのように構造化され、どのように他のレイヤーから使用されるかによって異なります。古典的な答えは、ビジネスイベントごとに抽象メソッドを定義することです(例:Confirm()、Acknowledge()、ShipDateChanged())。たとえばあなたが使用している場合C#では、Orderオブジェクトからの着信イベントと発信イベントを選択することができます。または、いくつかの混合物またはその組み合わせを試みることができます。主なポイントは、SetOrderState()インターフェイスはあまり記述的ではなく、不器用な実装(各OrderStateクラスの大きなメソッド)につながる可能性が高いということです。

また、さまざまな状態の変化の周りにたくさんのコードを持っていない場合、あなたのクラス(あなたの特定のメソッドやイベントから呼び出される)の内部のSetState()メソッドはOKかもしれませんが、それを外部インタフェースとして公開します。欠点は、内部のIOrderStateインターフェイスのメソッドと外部に公開されているOrderインターフェイスのメソッドが重複する可能性があることです。

これは判決ではありますが、私があなたの場合は、あなたの国の実装の詳細をクライアントに公開しないようにあなたの本能に行きます。 Orderクラスを使用するコードは、読みやすく分かりやすいものでなければなりません。

+0

ご意見ありがとうございます。私は私のアーキテクチャのいくつかのさらなる明確化を追加しました、うまくいけば、これは助けてください。 Orderクラスをできるだけ軽量化しようとすると、実際に自分自身にとってより難しくなっているのだろうか? – James

1

私は、状態間の移行はクラスにあるべきだと思います。

例として、ある種のアクションをその順序で実行すると、その順序は他の状態に移動する方法を知っています。例:

public void setPaid(int amount) 
{ 
    //Code to pay. 
    this.State = new PaidState(); //State implements the IState Interface 
} 

これ以外の方法として、このようなメソッドを実装する新しいClass of Transformerを作成することができます。

public class Transformer 
{ 
    public static void setState(Order o, IState s) 
    { 
     //Change the State. 
    } 
} 

それとも前年比が国を設定するために列挙型を使用することができます。

public class Transformer 
{ 
    public static void setState(Order o, StatesEnum s) 
    { 
     //Change the State. 
    } 
} 

しかし、私は、自身の状態を操作するためのクラスをお勧め。しかし、複雑さを覚えておいてください。

よろしく!

+0

ご意見ありがとうございます。私はOrderクラスをできるだけシンプルにしようとしていましたが、代わりに私のサービスレイヤーを操作して外部から評価するようにしました(私はTransformerの提案に似ていると思います)。 Orderクラスでこれを行うメリットは何ですか? – James

+0

こんにちはジェームス; 1)状態遷移の知識をすべて、良いクラスに委譲します。 2)他人に状態を操作させないでください(時にはエラーが発生する可能性があります) 3)状態遷移フローを簡単に制御できます。サードパーティの評価には依存しません。クラスはどのように変更するかを知っています:) – MRFerocius

関連する問題