命令模式(c++实现)

命令模式

模式定义

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

模式动机

  • 敏捷开发的原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。

UML类图

源码实现

  • command.h
#include "chef.h"

class Command
{
public:
    Command(Chef* chef);
    virtual ~Command();
    virtual void ExcuteCmd();

protected:
    Chef*   m_Chef;
};
  • chef.h
class Chef
{
public:
    Chef();
    void KungPaoChicken();
    void FishFlavoredShreddedPork();
    void BigPlateChicken();
};
  • chef.cpp
#include "chef.h"
#include <iostream>
Chef::Chef()
{

}

void Chef::KungPaoChicken()
{
    std::cout << "宫保鸡丁" << std::endl;
}

void Chef::FishFlavoredShreddedPork()
{
    std::cout << "鱼香肉丝" << std::endl;
}

void Chef::BigPlateChicken()
{
    std::cout << "大盘鸡" << std::endl;
}

  • kungpaochickencmd.h
#include "command.h"
#include "chef.h"

class KungPaoChickenCmd : public Command
{
public:
    KungPaoChickenCmd(Chef* chef);
    void ExcuteCmd() override;
};
  • kungpaochickencmd.cpp
#include "kungpaochickencmd.h"

KungPaoChickenCmd::KungPaoChickenCmd(Chef* chef)
    :Command(chef)
{

}

void KungPaoChickenCmd::ExcuteCmd()
{
    m_Chef->KungPaoChicken();
}
  • waiter.h
#include <list>
#include <command.h>

class Waiter
{
public:
    Waiter();
    void AddCmd(Command* cmd);
    void DelCmd(Command* cmd);
    void Nodify();
private:
    std::list<Command*>     m_CmdList;
};
  • waiter.cpp
#include "waiter.h"

Waiter::Waiter()
{

}

void Waiter::AddCmd(Command *cmd)
{
    m_CmdList.push_back(cmd);
}

void Waiter::DelCmd(Command *cmd)
{
    m_CmdList.remove(cmd);
}

void Waiter::Nodify()
{
    for(auto cmd : m_CmdList)
    {
        if(cmd)
            cmd->ExcuteCmd();
    }
}
  • main.cpp
#include <iostream>
#include "fishflavoredshreddedporkcmd.h"
#include "kungpaochickencmd.h"
#include "bigplatechickencmd.h"
#include "waiter.h"
#include <memory>
int main()
{
    Chef* chef = new Chef();
    Waiter waiter;

    std::shared_ptr<FishFlavoredShreddedPorkCmd> ffspc = std::make_shared<FishFlavoredShreddedPorkCmd>(chef);
    std::shared_ptr<KungPaoChickenCmd> kpcc = std::make_shared<KungPaoChickenCmd>(chef);
    std::shared_ptr<BigPlateChickenCmd> bpcc = std::make_shared<BigPlateChickenCmd>(chef);

    waiter.AddCmd(ffspc.get());
    waiter.AddCmd(kpcc.get());
    waiter.AddCmd(bpcc.get());
    //        waiter.DelCmd(kpcc.get);

    waiter.Nodify();
    return 0;
}

  • 运行结果

鱼香肉丝

宫保鸡丁

大盘鸡

优点

命令模式的优点

  • 它能较容易的设计一个命令队列;
  • 在需要的情况下,可以较容易的将命令计入日志;
  • 允许接收请求的一方决定是否要否决请求;
  • 可以容易的实现对请求的撤销和重做;
  • 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易;
  • 把请求一个操作的对象与知道怎么执行一个操作的对象分隔开;

缺点

模式的缺点