experiment: State machine

找了一篇关于 <<State Pattern>>的文章,简明易懂。


<<Understanding State Pattern in C++>>
http://www.codeproject.com/KB/architecture/StatePatternBy_Sarath__.aspx?bmkres=success


以前的工程中上位机和下位机通讯的代码,也见到过c++的状态机,但是理解起来不明了, 可能和原作者的风格有关。不如这个文章说的那么通俗。

看了demo后发现, 他的状态机没有传入状态管理指针, 状态完全是固定的变化. 如果状态节点数量或状态转换条件发生了变化,  维护起来不是很方便. 

如果不传入状态管理指针, 状态响应用户请求后, 操作的数据在状态之外也无法知道.

相反, 通过将状态管理指针传入状态实例, 状态实例操作的数据和状态机的变化,都在状态管理指针中, 贴近实际应用.


在<<研磨设计模式>>中的State模式中, 给出的Demo很实用. 原版是JAVA, 我做了实验, 修改成了C++版.

/**
* @file srcVoteState.cpp
* <<研磨设计模式>>中 State模式 Demo的C++版
*/

#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <string>
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>

#include "TypeDefine.h"
#include "VoteManager.h"

int _tmain(int argc, _TCHAR* argv[])
{
	INT i = 0;
	INT iVoteCntRc = 0;
	DWORD dwRc = 0;
	CONST TCHAR * pcUserName = _T("usr1");
	CONST TCHAR * pcUserOption = _T("excellence");
	std::wstring strRc;

	_tsetlocale(LC_ALL, _T("Chinese_People's Republic of China.936"));

	CVoteManager VoteManager;

	for(i = 0; i < 20; i++)
	{
		dwRc = VoteManager.vote((TYPE_USER_NAME)pcUserName, 
			(TYPE_VOTE_OPTION)pcUserOption, iVoteCntRc, strRc);

		_tprintf(_T("用户<%s> 第[%d]次投票[%s] 投票数量[%d],")\
			_T(" 投票结果[%s]\n"),
			pcUserName,
			i + 1,
			(RC_VOTE_OK == dwRc) ? _T("成功") : _T("失败"),
			iVoteCntRc, 
			strRc.c_str());
	}

	/** run results
	用户<usr1> 第[1]次投票[成功] 投票数量[1], 投票结果[投票成功]
	用户<usr1> 第[2]次投票[失败] 投票数量[2], 投票结果[请不要重复投票]
	用户<usr1> 第[3]次投票[失败] 投票数量[3], 投票结果[请不要重复投票]
	用户<usr1> 第[4]次投票[失败] 投票数量[4], 投票结果[请不要重复投票]
	用户<usr1> 第[5]次投票[失败] 投票数量[5], 投票结果[请不要重复投票]
	用户<usr1> 第[6]次投票[失败] 投票数量[6], 投票结果[恶意投票, 取消投票资格]
	用户<usr1> 第[7]次投票[失败] 投票数量[7], 投票结果[恶意投票, 取消投票资格]
	用户<usr1> 第[8]次投票[失败] 投票数量[8], 投票结果[恶意投票, 取消投票资格]
	用户<usr1> 第[9]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[10]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[11]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[12]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[13]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[14]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[15]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[16]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[17]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[18]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[19]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	用户<usr1> 第[20]次投票[失败] 投票数量[8], 投票结果[黑名单用户, 取消投票资格]
	*/

	getchar();
	return 0;
}

experiment: State machine_第1张图片

experiment: State machine_第2张图片

上位机和设备进行通讯处理时, 用状态机比较恰当.  和通讯有关的数据放到状态管理器里面, 因为通讯的状态转换比较频繁, 预先产生通讯时可能出现的N个状态机, 在程序结束的时候释放. 根据初始状态的不同,将通讯帧处理分散到对应的状态处理, 将通讯的处理解耦. 


通讯时可能出现的状态有: 连接设备, 发送, 接收, 超时, 重发, 断开设备.


    /**
    * 状态机只负责单一的状态处理
    * 状态机执行结束后, 在状态管理器中, 根据执行的结果, 进行状态的转换.
    * 因为状态机没有责任知道下一个状态到底是啥. 否则就则加了耦合
    */


demo rul  : srcStateMachine_V2011_1024_0218.rar





你可能感兴趣的:(experiment: State machine)