C++ 设计模式 命令模式

以下内容均来自GeekBand极客班C++ 设计模式课程(李建忠老师主讲)

Command

“行为变化”模式

在组件的构建过程中,组件行为的变化经常导致组件本身剧烈的变化。“行为变化”模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现两者之间的松耦合。

典型模式:

Command

Visitor

成员函数一般分为两类,虚函数和非虚函数(或静态),非虚函数(或静态)是编译的时候以地址的形式直接绑定,虚函数是运行时通过虚函数指针进行绑定

动机(Motivation)

在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。

但在某些场合——比如需要对行为进行“记录、撤销/重(undo/redo)、事务”等处理,这种无法抵御变化的紧耦合是不合适的。

在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

《设计模式》GOF的定义:

将一个请求(行为)封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作

C++ 设计模式 命令模式_第1张图片

红色部分为稳定部分,蓝色部分是变化部分

示例

现在有一个抽象的命令存在

class Command{
public:
    virtual void execute() = 0;
};

我们下面有很多命令,将这些命令全部继承于抽象命令

class ConcreteCommand1 : public Command{
    string arg;
public:
    ConcreteCommand1(const string & a) : arg(a){}
    void execute(){
        cout<<"#1 process..."<

可以穿件一个参数命令列

class MarcoCommand : public Command{
    vector commands;
public:
    void addCommand(Command * c){ commands.push_back(c); }
    void execute(){
        for(auto item:commands){
            item->execute();
        }
    }
};

具体的操作如下:创建命令,并添加到命令列,然后进行执行

各式命令已经变成了具体的对象,可以针对这些对象进行操作

    ConcreteCommand1 command1(receiver,"Arg ###");//命令1
    ConcreteCommand1 command2(receiver,"Arg $$$");//,命令2

    MarcoCommand macro;//构成一个命令列
    macro.addCommand(&command1);
    macro.addCommand(&command2);

    macro.execute();//执行命令

 

要点总结

Command模式的根本目的在于将“行为请求者”与:行为实现者解耦,在面对对象语言中,常见的实现手段是“将行为抽象为对象”

实现Command接口的具体命令对象ConcreteCommand有时候根据需要可能会保存一些额外的状态信息。通过使用Composite模式,可以将多个“命令”封装为一个“复合命令”MacroCommand

Command模式与C++中的函数对象有些类似。但两者定义行为接口的规范有所区别:Command以面向对象中的“接口——实现”来定义行为接口规范,更严格,但性能损失(毕竟是运行时绑定)

C++函数对象以函数签名来定义行为接口规范,更灵活,性能更高。

你可能感兴趣的:(重构)