繁体   English   中英

如何确定状态模式的状态

[英]How to determine states for the State pattern

我正在开发一个 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);
};

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

创建PosAuthorisationPosReadCardData等状态以便它们对应于 POS 功能是否有意义? 大概没意思吧...

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

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

任何意见,将不胜感激。

非常感谢。

状态通常是用动词来描述的。 例如, 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 以请求用户数据,并切换到waiting for authorization information状态,然后做其他事情, 等等。

希望有帮助。

通常在代码中实现真实世界的范式反射是好的。 如果您:

  • 可以命名它们
  • 知道限制
  • 知道它可以过渡到哪些状态

大多数硬件模块被实现为状态机。 状态模式很容易理解,所以你不太可能有维护问题

我认为你会特别喜欢重新实现不适用的虚拟成员以在没有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!!");}
};

希望这可以帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM