• 第30章 混编模式(1)


    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
    file2
    file3
    file4
    ";
        }
    
        //ls -l命令
        static string ls_l(string path)
        {
            string str = "drw-rw-rw root system 1024 2016-7-13 20:42 file1
    ";
            str += "drw-rw-rw root system 1024 2016-7-13 20:42 file2
    ";
            str += "drw-rw-rw root system 1024 2016-7-13 20:42 file3
    ";
            return str;
        }
    
        //ls -a命令
        static string ls_a(string path)
        {
            string str = ".
    ..
    file1
    file2
    file3";
            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 +="
    " + 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)模式,具体来说就是命令模式作为责任链模式的排头兵,由命令模式分发具体的消息到责任链模式。

  • 相关阅读:
    原码、反码、补码详解
    进制转换
    目录
    Window【目录】
    排序算法——冒泡排序
    算法的时间复杂度与空间复杂度
    排序算法
    递归—八皇后问题
    递归—迷宫问题
    递归
  • 原文地址:https://www.cnblogs.com/5iedu/p/5677251.html
Copyright © 2020-2023  润新知