0

LAN 経由で POS (Point of sale) 端末を制御するために使用される DLL を開発しています。

DLL は、次のような操作を実行するコマンドを提供します。

  • ログオン
  • ログオフ
  • 認可
  • カードデータの読み取り
  • キャンセル
  • 返金
  • ネットワーク診断

また、DLL は Connect() および Disconnect() 関数を提供します。

POS 端末はさまざまな状態になる可能性があるため、State パターンは DLL で使用される可能性があると考えています。

擬似コード:

// My DLL
class Pos
{
public:
    Pos();
    ~Pos();

    bool Connect();
    bool Disconnect();

    bool DoLogon() { m_pCurrentPosState->DoLogon(this); }
    bool DoLogoff() { m_pCurrentPosState->DoLogoff(this); }
    bool DoAuthorisation() { m_pCurrentPosState->DoAuthorisation(this); }
    bool DoReadCardData() { m_pCurrentPosState->DoReadCardData(this); }
    bool DoCancellation() { m_pCurrentPosState->DoCancellation(this); }
    bool DoRefund() { m_pCurrentPosState->DoRefund(this); }
    bool DoNetworkDiagnosis() { m_pCurrentPosState->DoNetworkDiagnosis(this); }
    ...

private:
    void ChangeState(PosState *pPosState) { m_pCurrentPosState = pPosState; }

private:
    friend class PosState;
    PosState *m_pCurrentPosState;
    ...
};

class PosState
{
public:
    // Implement default behavior for all command requests.
    virtual bool DoLogon(Pos *pPos) {}
    virtual bool DoLogoff(Pos *pPos) {}
    virtual bool DoAuthorisation(Pos *pPos) {}
    virtual bool DoReadCardData(Pos *pPos) {}
    virtual bool DoCancellation(Pos *pPos) {}
    virtual bool DoRefund(Pos *pPos) {}
    virtual bool DoNetworkDiagnosis(Pos *pPos) {}

protected:
    void ChangeState(Pos *pPos, PosState *pPosState);
};

class PosLoggedon : public PosState
{
public:
    static PosState* Instance();

    // Implement state-specific behavior.
    bool DoLogoff(Pos *pPos);
    bool DoAuthorisation(Pos *pPos);
    bool DoReadCardData(Pos *pPos);
    bool DoCancellation(Pos *pPos);
    bool DoRefund(Pos *pPos);
    bool DoNetworkDiagnosis(Pos *pPos);
};

class PosLoggedoff : public PosState
{
public:
    static PosState* Instance();

    // Implement state-specific behavior.
    bool DoLogon(Pos *pPos);
    bool DoAuthorisation(Pos *pPos);
    bool DoReadCardData(Pos *pPos);
    bool DoCancellation(Pos *pPos);
    bool DoRefund(Pos *pPos);
    bool DoNetworkDiagnosis(Pos *pPos);
};

PosLoggedonPosLoggedoffはどちらも有効と考えることができる 2 つの状態ですが、他の状態を判断する方法がわかりません。

PosAuthorisationPosReadCardDataなどの状態を作成して、POS 関数に対応させることは理にかなっていますか? たぶん意味不明…

「進行中の現在のコマンド」と「現在の POS 状態」が混在しているため、状態パターンを正しく使用する方法について混乱しています。

おそらく、PosCommandInProgressのような状態が必要ですか?

アドバイスをいただければ幸いです。

どうもありがとう。

4

2 に答える 2

1

状態は通常、動詞で記述されたものです。たとえばparsing、状態のように聞こえます。UserLogged状態であるため鳴りませんが、状態を変えることができるイベントのように聞こえます。

ステートマシンが必要な場合は、どのアクションにさまざまな状態が含まれ、どのアクションに含まれないかを判断する必要があります。たとえば、状態が存在する可能性がありますwaiting for input。ユーザーが何かをする必要があるたびに、マシンはこの状態になります。waiting for address input、、などのような多くの状態を作成する必要はおそらくありません。waiting for name inputこれらはすべて実際にはwaiting for input状態であるためです。

さて、それぞれの州には2つのことがあります。最初は、ステートマシンが状態にある間に実行できることのリストです。たとえば、ユーザーが名前を入力するのを待っている状態waiting for inputで、かわいい子猫の写真を表示することはできますが、ユーザーの銀行口座で操作を実行することはできません。

2つ目は、現在のマシンでマシンが変更できる状態のリストです。たとえば、状態からにwaiting for input変更できますshowing the greeting message

したがって、状態とコマンドを混在させないでください。コマンドは状態で実行でき、コマンドによってマシンの状態を変更できますが、同じではありません。

DLLができる場合

Logon
Logoff
Authorisation
Read card data
Cancellation
Refund
Network diagnosis

connectingそうすると、 おそらく、、、、、、のような状態に waiting for authorization information inputなります。authorizingwaiting for account operation choiceexecuting account operationlogging off

したがって、connectingおそらくネットワーク診断を実行して、接続が可能かどうかを確認し、接続を確立し、サーバーの応答を取得し、UIを表示してユーザーデータを要求し、waiting for authorization information状態に切り替えてから、他のことを行う必要があります。

お役に立てば幸いです。

于 2012-07-31T09:58:11.930 に答える
1

通常、コードに現実世界のパラダイム リフレクションを実装することをお勧めします。次の場合、状態は非常に適切です。

  • それらに名前を付けることができます
  • 限界を知る
  • どの状態に遷移できるかを知る

ハードウェア モジュールの大部分は、ステート マシンとして実装されます。状態のパターンがわかりやすいので、メンテナンスのトラブルが起こりにくい

適切でない仮想メンバーを再実装してエラーをスローすることを特に好むと思いますif (state == XX) ... else if (state == YY) ...:)

たとえば、コードではないもの:

interface AbstractBeing
{
    void sleep();
    void eat();
    void lieDownAndDie();
};


class ImAlive implements AbstractBeing
{
    void sleep() {doZzzzzzz();}
    void eat() {nomNomNomNom();}
    void lieDownAndDie() {turnUndead();}
};

class ImUndead implements AbstractBeing
{
    void sleep() {throw error("zombies aint need no sleep");}
    void eat() {seekBrainzzzz();}
    void lieDownAndDie() {throw error("no you!!");}
};

お役に立てれば

于 2012-07-31T10:08:15.753 に答える