C++ 如何确定状态模式的状态

C++ 如何确定状态模式的状态,c++,sockets,design-patterns,network-programming,state-pattern,C++,Sockets,Design Patterns,Network Programming,State Pattern,我正在开发一个DLL,用于通过局域网控制POS(销售点)终端 DLL提供用于执行以下操作的命令: 登录 注销 授权 读卡数据 取消 退款 网络诊断 DLL还提供Connect()和Disconnect()函数 由于POS终端可以处于各种状态,我认为状态模式可能会在DLL中使用 伪代码: // My DLL class Pos { public: Pos(); ~Pos(); bool Connect(); bool Disconnect(); bo

我正在开发一个DLL,用于通过局域网控制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都是我认为有效的两种状态,但我不确定如何确定其他状态

创建类似于POSAuthorizationPosReadCardData等状态以使其对应于POS功能是否有意义?也许这没什么意义

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

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

如有任何建议,将不胜感激


非常感谢。

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

如果您想要一个状态机,您需要确定哪些操作涉及不同的状态,哪些不涉及。例如,可能存在等待输入的状态
。每次用户需要做某事时,机器都会进入这种状态。可能不需要创建很多状态,比如
等待地址输入
等待名称输入
,等等,因为它们实际上都是
等待输入
状态

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

第二件事是机器在当前状态期间可以更改的状态列表。例如,从等待输入的状态
变为显示问候语的状态

因此,不要将状态与命令混合使用。命令可以在不同的状态下执行,并且命令可以使机器改变其状态,但它们是不同的

如果你的DLL可以

然后您可能会出现如下状态:
连接
等待授权信息输入
授权
等待帐户操作选择
执行帐户操作
注销

因此,在
连接
中,您可能需要运行网络诊断以检查是否可以连接,然后建立连接,获取服务器响应,显示一些UI以请求用户数据,并切换到
等待授权信息
状态,然后执行其他操作,依此类推


希望有帮助

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

  • 你能说出他们的名字吗
  • 了解局限性
  • 知道它可以传输到什么州
大多数硬件模块都实现为状态机。状态模式很容易理解,所以不太可能出现维护问题

我认为您特别喜欢重新实现不适用的虚拟成员,以便在没有
if(state==XX)的情况下抛出错误。。。否则,如果(状态==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!!");}
};

希望,这有助于

@Roman-我不太清楚您所说的“重新实现不适用的虚拟成员以在没有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!!");}
};