第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 类图及说明

第30章 混编模式(1) 

(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 "file1nfile2nfile3nfile4n";
    }

    //ls -l命令
    static string ls_l(string path)
    {
        string str = "drw-rw-rw root system 1024 2016-7-13 20:42 file1n";
        str += "drw-rw-rw root system 1024 2016-7-13 20:42 file2n";
        str += "drw-rw-rw root system 1024 2016-7-13 20:42 file3n";
        return str;
    }

    //ls -a命令
    static string ls_a(string path)
    {
        string str = ".n..nfile1nfile2nfile3";
        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)模式,具体来说就是命令模式作为责任链模式的排头兵,由命令模式分发具体的消息到责任链模式。

原文链接: https://www.cnblogs.com/5iedu/p/5677251.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    第30章 混编模式(1)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/394043

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月3日 下午3:36
下一篇 2023年4月3日 下午3:36

相关推荐