如何确定State模式的状态

时间:2012-07-31 09:32:15

标签: c++ sockets design-patterns network-programming state

我正在开发一个用于通过LAN控制POS(销售点)终端的DLL。

DLL提供执行以下操作的命令:

  • 登录
  • 注销
  • 授权
  • 读卡数据
  • 取消
  • 退款
  • 网络诊断

此外,DLL还提供了Connect()和Disconnect()函数。

由于POS终端可以处于各种状态,我认为状态模式可能会在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);
};

PosLoggedon PosLoggedoff 是我认为有效的两种状态,但我不确定如何确定其他状态。

创建像 PosAuthorisation PosReadCardData 等状态以便它们对应于POS功能是否有意义?可能它没有意义......

我对如何正确使用状态模式感到困惑,因为我正在混合“正在进行当前命令”和“当前POS状态”。

也许我需要像 PosCommandInProgress 这样的状态?

任何建议都将受到赞赏。

非常感谢。

2 个答案:

答案 0 :(得分:1)

状态通常用动词描述。例如,parsing听起来像一个州。 UserLogged听起来不是一个状态,听起来更像是一个可以改变状态的事件。

如果需要状态机,则需要确定哪些操作涉及不同的状态,哪些不涉及。例如,可以有状态waiting for input。每次用户需要做某事时,机器就会变成这种状态。可能没有必要制作很多状态,例如waiting for address inputwaiting for name input等等,因为它们实际上都是waiting for input状态。

现在,每个州都有两件事。首先是状态机在状态时可以执行的操作的列表。例如,如果它正在等待用户输入他的名字,当处于状态waiting for input时,它可以显示可爱的小猫的图片,但它肯定不能用用户银行账户执行操作。

第二件事是机器可以在当前状态下更改的状态列表。例如,从州waiting for input开始,它可以更改为showing the greeting message

所以,使用命令混合状态。命令可以在状态下执行,命令可以使机器改变它的状态,但它们不一样。

如果您的DLL可以

Logon
Logoff
Authorisation
Read card data
Cancellation
Refund
Network diagnosis

那么您可能会有connectingwaiting for authorization information inputauthorizingwaiting for account operation choiceexecuting account operationlogging off等州。

因此,在connecting中,您可能需要运行网络诊断以检查是否可以连接,然后建立连接,获取服务器响应,显示一些UI以请求用户数据,并切换到{{1状态,然后做其他事情,等等。

希望有所帮助。

答案 1 :(得分: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!!");}
};

希望,这有帮助