从实例重温工厂模式和单件模式

来源:互联网 发布:直播配音软件 编辑:程序博客网 时间:2024/04/27 15:27
本文由恋花蝶最初发表于:http://blog.csdn.net/lanphaday,你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。
 
http://community.csdn.net/Expert/topic/4892/4892570.xml?temp=.8727381
今天一个好朋友发了上面这个贴,并邀我过去看看。就去看了看,当时觉得应该用工厂模式去解决,随便写了几句上去,后来又有冲动想写一下代码,正好重温一下经典的工厂模式,就写了如下代码。主要应用了工厂模式和单件模式。
现在如果要增加新的指令需要修改的地方也是相当地少:只要继承自CCommand,并实现自己的处理函数,然后向类工厂登记一下就可以了。
废话不多说了,看代码吧。感觉写这个东西学到不少东西,所谓温故而知新嘛。
 
先看问题:
有一个脚本文件,每行放一个命令,格式如下:
 
Name[,Parameter[,Value]]
 
其中,Parameter 和 Value 是可以省略的。Command分为不同的种类,对于特定的种类,Parameter 和 Value 是不是出现是一定的,如 "START"命令就没有Parameter 和 Value ,而"SEND"命令就有。头和我说,用类的层次结构来表示,外面在套一个解析类。我是这样做的
 
class CCommand{
    string Name;
    string Parameter;
    string Value;
};
 
那么,按照我们头的说法,我需要:
class CStartCommang : public CCommand{
    //在这里我需要做什么呢??
}
 
解析类CScriptExplain又该怎么定义呢?
我的参考代码,拷贝到一个.cpp文件中,即可编译、执行。我用的是VC6,相信MS的编译器也可以,GCC、BCB、DevC++应该也行。
#pragma warning(disable:4786)
 
#include
#include
#include
#include
#include
 
//也可以采用构造函数无参,doCommand有参的方式,那样就可以全部CCommand的派生类做成单件。
class CCommand
{
protected:
       CCommand(){}
       CCommand(const std::string& strCmd):m_strCmd(strCmd){}
public:
       virtual ~CCommand(){}
       virtual void doCommand()=0;
       static CCommand* CreateInstance(const std::string& strCmd);
       const std::string& GetCommandString(){return m_strCmd;}
private:
       std::string m_strCmd;
};
 
class CStartCommand:public CCommand
{
private:
       CStartCommand(){}
       CStartCommand(const std::string& strCmd):CCommand(strCmd)
       {
              //在这里解释strCmd里的Param和Value等
       }
public:
       virtual ~CStartCommand(){}
       void doCommand()
       {
              //在这里做这个命令要做的事
              std::cout << "Doing Start Command!/t" << GetCommandString() << std::endl;
       }
       static CCommand* CreateInstance(const std::string& strCmd)
       {
              CCommand* pCmd = new CStartCommand(strCmd);
              return pCmd;
       }
};
 
class CSendCommand:public CCommand
{
private:
       CSendCommand(){}
       CSendCommand(const std::string& strCmd):CCommand(strCmd)
       {
              //在这里解释strCmd里的Param和Value等
       }
public:
       virtual ~CSendCommand(){}
       void doCommand()
       {
              //在这里做这个命令要做的事
              std::cout << "Doing Send Command!/t" << GetCommandString() << std::endl;
       }
       static CCommand* CreateInstance(const std::string& strCmd)
       {
              CCommand* pCmd = new CSendCommand(strCmd);
              return pCmd;
       }
};
 
typedef CCommand*(*CreateInstanceFunc)(const std::string&);
 
class CCommandFactory
{
private:
       CCommandFactory(){}
 
public:
       virtual ~CCommandFactory(){}
       static CCommandFactory* GetInstance()
       {
              static CCommandFactory ins = CCommandFactory();
              return &ins;
       }
       void AddCommandFunc(std::string& strCmdName, CreateInstanceFunc func)
       {
              m_CommandFuncMap[strCmdName] = func;
       }
       CCommand* CreateCommand(std::string& strCmdName, std::string strCmd)
       {
              return m_CommandFuncMap[strCmdName](strCmd);
       }
       void ReleaseCommand(CCommand* p)
       {
              assert(p);
              delete p;
       }
private:
       std::map m_CommandFuncMap;
};
 
class CScriptExplain
{
public:
       void doFile(const char* strFileName)
       {
              CCommandFactory* pFactory = CCommandFactory::GetInstance();
              std::ifstream f(strFileName);
#define MAX_CMD_LEN 256
              char strCmd[MAX_CMD_LEN];
              char tmp[MAX_CMD_LEN];
              do{
                     f.getline(strCmd, MAX_CMD_LEN);
                     if(strlen(strCmd)==0)break;
                     int idx = 0;
                     for(; idx < MAX_CMD_LEN; ++idx)
                     {
                            if(strCmd[idx]==','||strCmd[idx]=='/0')break;
                            tmp[idx] = strCmd[idx];
                     }
                     if(idx == MAX_CMD_LEN)break;
                     tmp[idx] = '/0';
                     CCommand* pCmd = pFactory->CreateCommand(std::string(tmp), std::string(strCmd+idx));
                     pCmd->doCommand();
                     pFactory->ReleaseCommand(pCmd);
              }while(true);
       }
};
 
int main()
{
       CCommandFactory* pFactory = CCommandFactory::GetInstance();
       pFactory->AddCommandFunc(std::string("Start"), CStartCommand::CreateInstance);
       pFactory->AddCommandFunc(std::string("Send"), CSendCommand::CreateInstance);
      
       CScriptExplain se;
       se.doFile("my_script.txt");
       return 0;
}

***************

my_script.txt的内容:

Start
Send,Port,5555
Send,Port,8888
Send,Port,8673




原创粉丝点击