0

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

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都是我认为有效的两个状态,但我不确定如何确定其他状态。

创建像PosAuthorisationPosReadCardData等状态以便它们对应于 POS 函数是否有意义?大概没有意义吧……

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

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

任何意见,将不胜感激。

非常感谢。

4

2 回答 2

1

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

如果您想要一个状态机,您需要确定哪些操作涉及不同的状态,哪些不涉及。例如,可以有一个 state waiting for input。每当用户需要做某事时,机器就会进入这种状态。可能不需要创建很多状态,比如waiting for address input,waiting for name input等等,因为它们实际上都是waiting for input状态。

现在,在每个州都有两件事。首先是状态机在state 中可以做的事情的列表。例如,在等待用户输入姓名的状态下waiting for input,可以显示可爱的小猫图片,但绝对不能对用户的银行账户进行操作。

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

因此,不要状态与命令混为一谈。命令可以在状态下执行,命令可以使机器改变它的状态,但它们并不相同。

如果你的 DLL 可以

Logon
Logoff
Authorisation
Read card data
Cancellation
Refund
Network diagnosis

那么你可能会有像connecting, waiting for authorization information input, authorizing, waiting for account operation choice, executing account operation,的状态logging 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 回答