2012-07-31 73 views
0

我正在開發一個用於通過局域網控制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); 
}; 

兩個PosLoggedonPosLoggedoff兩種狀態,我能想到是有效的,但我不知道如何確定等。

是否有意義像PosAuthorisationPosReadCardData等,使他們對應POS功能創建國家?可能它沒有任何意義......

我很困惑,因爲我在混合「當前命令進行中」和「當前POS狀態」,因此如何正確使用狀態模式。

也許我需要一個像PosCommandInProgress

任何意見,將不勝感激。

非常感謝。

回答

1

狀態通常用動詞來描述。例如,parsing聽起來像一個狀態。 UserLogged聽起來不像是一個狀態,它聽起來更像是一個可以改變狀態的事件。

如果你想要一個狀態機,你需要確定哪些操作涉及不同的狀態,哪些不需要。例如,可以有一個狀態waiting for input。每次用戶需要做某件事時,機器都會變成此狀態。可能不需要製作諸如waiting for address input,waiting 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

通常在代碼中實現真實世界的範例反射是很好的。國家是非常合適的,如果你:

  • 能說出他們
  • 知道限制
  • 知道是什麼狀態就可以轉換到

硬件的大部分模塊被實現爲狀態機。 State模式是很容易理解,所以你不太可能有維修問題

我想你會特別喜歡重新實現不適虛擬成員拋出錯誤,而if (state == XX) ... else if (state == YY) ... :)

例如有些不-A-代碼:

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!!");} 
}; 

希望,這有助於

+0

@羅馬 - 我不太清楚你的意思是「不適用重新實現虛擬成員拋出錯誤,而如果(狀態== XX)......否則,如果(狀態== YY)」。你能給我更多的信息嗎?乾杯。 – jpen 2012-07-31 10:36:44

+0

好的,編輯我的帖子添加一些例子 – 2012-07-31 10:50:42

+0

哦,我明白了。很好的樣本,哈哈! – jpen 2012-07-31 10:59:10