30.1 命令链模式(命令模式+责任链模式)
30.1.1 UNIX下的命令规则(如ls)
(1)命令名为小写字母
(2)命令名、选项、操作数之间以空格分隔,空格数量不受限制
(3)选项之间可以组合使用,也可以单独拆分使用
(4)选项以“-”开头
30.1.2 ls命令详解(如ls -a -l /usr)
(1)ls:简单列出一个目录下的文件;ls –l:详细列出目录下的文件;ls –a:列出目录下包含的隐藏文件,主要是“.”开头的文件。
(2)每一个ls命令都有操作数(如usr目录),默认操作数为当前目录。
(3)选项不可重复,如ls –l –l –s,解析出的选项应该只有两个:l选项和s选项
30.1.3 类图及说明
(1)CommandVo:命令的值对象,它把一个命令解析为命令名、选项、操作数。例如“ls –l /usr”命令分别解析为getCommandName、getparam、getData三个方法的返回值
(2)CommandChain:根据命令选项生成相应的命令处理对象,如“ls –l –a /usr”将生成LS、LS_L、LS_A等3个对象。
(3)FileManager为资源管理器,根据输入的命令调用相应的API来显示目录信息。这里为简单起见,只是用字符串来简单模拟。
【编程实验】搬移UNIX的命令
//设计模式混编——命令模式+责任链模式 //实例:搬移UNIX的命令 #include <iostream> #include <string> #include <vector> #include <list> #include <map> using namespace std; //*******************************************辅助类*********************************** //命令对象:CommandVo class CommandVo { public: //定义参数名与参数的分隔符号,一般是空格 static const string DIVIDE_FLAG; //定义参数前的符号,UNIX一般是-,如ls -la static const string PREFIX; private: //命令名,如ls,du string commandName; //参数列表(使用map是为了防止参数重复。如ls -l -l -s) map<string,string> paramList; //操作数列表 vector<string> dataList; void init(string& commandStr) { //常规判断 if(commandStr.length() >0) { //根据分隔符号拆分执行符号 vector<string> complexStr; split(commandStr, DIVIDE_FLAG, complexStr); //第一个参数是执行符号 commandName = complexStr[0]; //把参数放入参数列表中 paramList[""] = ""; for(size_t i=1; i<complexStr.size(); i++) { string str = complexStr[i]; //包括前缀符号,认为是参数 trim(str); if(str.find(PREFIX)==0) { str = str.replace(0,1,""); paramList[str] = str; } else { if (str !="") dataList.push_back(str); } } } else { //传递的命令错误 cout << "命令解析失败,必须传递一个命令才能执行" << endl; } } void split(const string src, const string delim, vector<string>& out) { size_t last = 0; size_t index = src.find_first_of(delim, last); while (index != std::string::npos) { out.push_back(src.substr(last, index-last)); last = index + 1; index = src.find_first_of(delim, last); } if (index-last>0) { out.push_back(src.substr(last, index-last)); } } string& trim(std::basic_string<char>& s) { const string p = " "; s.erase(0, s.find_first_not_of(p)); s.erase(s.find_last_not_of(p) + 1); return s; } public: //通过构造函数传递进来命令 CommandVo(string commandStr) { commandName = ""; init(commandStr); } //获取命令名 string getCommandName(){return commandName;} //获取参数列表 map<string,string>& getParam() { //为了方便处理空参数 if(paramList.size() == 0) { paramList[""]=""; } return paramList; } //获取操作数 vector<string>& getData(){return dataList;} //获得操作数,返回值为string类型 string formatData() { //没有操作数 if(dataList.size() == 0) { return ""; } else { string ret =""; vector<string>::iterator iter= dataList.begin(); while (iter != dataList.end()) { ret += *iter + " "; ++iter; } return ret; } } }; const string CommandVo::DIVIDE_FLAG = " "; const string CommandVo::PREFIX = "-"; //文件管理类 class FileManager { public: //ls命令 static string ls(string path) { return "file1\nfile2\nfile3\nfile4\n"; } //ls -l命令 static string ls_l(string path) { string str = "drw-rw-rw root system 1024 2016-7-13 20:42 file1\n"; str += "drw-rw-rw root system 1024 2016-7-13 20:42 file2\n"; str += "drw-rw-rw root system 1024 2016-7-13 20:42 file3\n"; return str; } //ls -a命令 static string ls_a(string path) { string str = ".\n..\nfile1\nfile2\nfile3"; return str; } }; //抽象命令名类(相当于责任链的handler角色) class CommandName { private: CommandName* nextOperator; public: string handleMessage(CommandVo& vo) { //处理结果 string result = ""; //判断是否是自己处理的参数 map<string,string>::iterator iter = vo.getParam().find(getOperateParam()); if(iter != vo.getParam().end() ) { result = echo(vo); if(nextOperator != NULL) { result +="\n" + nextOperator->handleMessage(vo); } } else { result = "命令无法执行"; } return result; } //设置剩余参数由谁来处理 void setNext(CommandName* cmdName) { nextOperator = cmdName; } virtual ~CommandName(){} protected: //每个处理者都要处理一个后缀参数 virtual string getOperateParam() = 0; //每个处理都必须实现处理任务 virtual string echo(CommandVo& vo) = 0; }; //抽象ls命令 class AbstractLS : public CommandName { public: //默认参数 static const string DEFAULT_PARAM; static const string A_PARAM; static const string L_PARAM; }; const string AbstractLS::DEFAULT_PARAM =""; const string AbstractLS::A_PARAM ="a"; const string AbstractLS::L_PARAM ="l"; //ls命令 class LS : public AbstractLS { protected: //最简单的ls命令 string echo(CommandVo& vo) { return FileManager::ls(vo.formatData()); } //参数 string getOperateParam() { return AbstractLS::DEFAULT_PARAM; } }; //ls-a命令 class LS_A : public AbstractLS { protected: //最简单的ls命令 string echo(CommandVo& vo) { return FileManager::ls_a(vo.formatData()); } //参数 string getOperateParam() { return AbstractLS::A_PARAM; } }; //ls-l命令 class LS_L : public AbstractLS { protected: //最简单的ls命令 string echo(CommandVo& vo) { return FileManager::ls_l(vo.formatData()); } //参数 string getOperateParam() { return AbstractLS::L_PARAM; } }; // class CommandChain { private: list<CommandName*> commandChain; map<string,string>& paramList; public: CommandChain(map<string, string>& paramList):paramList(paramList) { buildChain(); }; //返回链表的首节点 CommandName* getFirstNode() { return commandChain.front(); } void buildChain() { //构造链表是有顺序的:LS-> LS_L -> LS_A map<string, string>::iterator iter = paramList.find(AbstractLS::DEFAULT_PARAM); if(iter !=paramList.end()) { CommandName* cmdLS = new LS(); commandChain.push_back(cmdLS); } iter = paramList.find(AbstractLS::L_PARAM); if(iter !=paramList.end()) { CommandName* cmdLSL = new LS_L(); commandChain.push_back(cmdLSL); } iter = paramList.find(AbstractLS::A_PARAM); if(iter !=paramList.end()) { CommandName* cmdLSA = new LS_A(); commandChain.push_back(cmdLSA); } list<CommandName*>::iterator it = commandChain.begin(); while( it != commandChain.end()) { CommandName* pre = *it; ++it; if (it == commandChain.end()) pre->setNext(NULL); else pre->setNext(*it); } } void deleteChain() { list<CommandName*>::iterator iter = commandChain.begin(); while( iter != commandChain.end()) { delete (*iter); ++iter; } commandChain.clear(); } ~CommandChain() { deleteChain(); } }; //*****************************Command**************************** //抽象命令角色 class Command { protected: CommandName* receiver; //建立链表,表头为命令的接收者,ls和du命令系列做法相同 //这里只演示ls命令系列组成的链表 public: Command(CommandName* receiver) { this->receiver = receiver; } virtual string execute(CommandVo& vo) = 0; virtual ~Command(){} }; //LSCommand class LSCommand :public Command { public: LSCommand(CommandName* commandName):Command(commandName){} string execute(CommandVo& vo) { return receiver->handleMessage(vo); } }; //******************************Invoker*************************** class Invoker { public: string exec(string commandStr) { //定义返回值 string ret =""; //首先解析命令 CommandVo vo(commandStr); CommandChain chain(vo.getParam()); //创建命令 Command* command = new LSCommand(chain.getFirstNode()); ret = command->execute(vo); delete command; return ret; } }; int main() { string cmd ="ls -l -a -l /usr /password"; Invoker invoker; string ret = invoker.exec(cmd); cout <<ret << endl; return 0; }; /*输出结果: */
30.1.4 小结
(1)责任链模式:负责对命令参数进行解析,而且所有的扩展都是增加链数量和节点,不涉及原有代码变更
(2)命令模式:负责命令的分发,把适当的命令分发到指定的链上。
(3)该框架还有一个名称,叫做“命令链”(Chain of Command)模式,具体来说就是命令模式作为责任链模式的排头兵,由命令模式分发具体的消息到责任链模式。
时间: 2024-10-02 11:48:50