第30章 混编模式

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

第30章 混编模式的相关文章

第30章 混编模式(3)

30.3 事件触发器的开发(观察者模式+中介者模式) 30.3.1 场景介绍 (1)有一产品它有多个触发事件(如创建事件.修改.删除),如创建文本框时触发OnCreate事件,修改时触发onChange事件,双击时触发onDblClick事件. (2)当产品触发事件时,会创建相应的产品事件对象(ProductEvent),并将这个事件对象传递给观察者,以便通知观察者该事件的发生. (3)观察者实现上是一个事件的分发者,相当于中介模式中的中介对象,会把这个事件分发者相应的事件处理对象. 30.3.

混编模式

OC为我们提供了混编模式,我们新建了三个类,Teacher,student,person,可以按照图中的方式找到对应的类来设计不同的管理模式,上边标红的语句是打开自动管理,下边的那一个是关闭自动管理.

Swift和OC混编

swift 语言出来后,可能新的项目直接使用swift来开发.但可能在过程中会遇到一些情况,某些已用OC写好的类或封装好的模块.不想再在swift 中再写一次,哪就使用混编. 这个在IOS8中是同意的. 先中简单的入手,先研究在同一个project文件夹下混合使用的情况. 为了演示.先准备两个类 第一个是swift语言写的类,文件名称为 act.swift 1.    import Foundation 2. 3.    class Act : NSObject 4.    { 5.      

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

背景 此篇文章,主要针对想要在原有Native工程的基础上集成Flutter的需求,所提供的混编方案的探讨. 官方方案的优缺点 (1)优点: 不需要每次 Run 起来之后,先进行 同步flutter代码(组件化Flutter后,因为组件化后flutter代码已经变为framework,所以每次进来需要先热更新同步代码)不需要单独搞一个组件进行集成,管理组件的版本,发布等.(2)缺点: 会非常耦合工程,需要修改工程配置,添加 BUILD PHASE 调用 flutter 中 xcode_backe

Xcode中C、C++、Object-C3种语言的混编

转自: http://hi.baidu.com/onejw/item/f34390c997cdc226a1b50ae http://www.cocoachina.com/ask/questions/show/57217 http://www.cnblogs.com/uyoug321/archive/2010/12/11/1903499.html Xcode中支持C.C++.Object-C3种语言的混编 Xcode中支持C.C++.Object-C3种语言的混编,那么如果想让编译器混编,只需要将

OC+swift混编

作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/34440159 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号fengsh998来支持我,谢谢! swift 语言出来后,可能新的项目直接使用swift来开发,但可能在过程中会遇到一些情况,某些已用OC写好的类或封装好的模块,不想再在swift 中再写一次,哪就使用混编.这个在IOS8中是允许的. 先中简单的入手,先研究在同一个工程目录下混合

30-ocARC基本概念ARM和MRC混编

 ARC ARC的原理是什么 当ARC开启时,编译器将自动在代码合适的地方插入retain, release和autorelease,而作为程序猿,完全不需要担心编译器会做错(除非开发者自己错用ARC了). ARC有什么优点 完全消除了手动管理内存的烦琐, 让程序猿更加专注于app的业务 基本上能够避免内存泄露 有时还能更加快速,因为编译器还可以执行某些优化 ARC的原则是什么?什么是强指针?什么是弱指针? 只要还有一个强指针变量指向对象,对象就会保持在内存中 1.强指针 默认所有指针变量都是强

iOS开发——技术精华Swift篇&amp;Swift 2.0和Objective-C2.0混编之第三方框架的使用

Swift 2.0和Objective-C2.0混编之第三方框架的使用 swift 语言是苹果公司在2014年的WWDC大会上发布的全新的编程语言.Swift语言继承了C语言以及Objective-C的特性,且克服了C语言的兼容性问题.Swift语言采用安全编程模式,且引入了多种新功能,使得编程工作更加简便,灵活! 2015年6月9日苹果又一次给所有开发之者带来了一个惊喜,那就是今年年底swift讲开源,者队iOS开发着来说无疑是一个值得兴奋的消息,可是就在这短短的几个月里面swift吸引了越来

iOS开发之ARC MRC混编

Xcode5之后,新建iOS工程,默认都是ARC模式,但是有时候我们的项目中需要用到一些第三方框架,我们下载下来却发现是非ARC的,这时候我们需要进行ARC和MRC混编. 第一种方式,Edit->Refactor,转换成ARC方式 著名的iOS网络框架ASIHTTPRequest就是MRC,我们试试能不能转换成ARC 点击Check,我们发现悲剧了 多数情况下这种方式都会出错,那该怎么办呢? 第二种方式,给编译器加标记 可以在Build Phases中的Compile Sources中加入编译标