设计模式——命令模式

转载来自:https://www.cnblogs.com/wzxNote/p/13305597.html

命令模式

目录

 

模式定义

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

模式动机

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

UML类图

设计模式——命令模式

在该类图中,我们看到三个角色:

  • Receiver接受者角色:该角色就是干活的角色,命令传递到这里是应该被执行的
  • Command命令角色:需要执行的所有命令都在这里声明
  • Invoker调用者角色:接收到命令,并执行命令

源码实现

  • 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()
{
    std::shared_ptr<Chef> chef = std::make_shared<Chef>();
    Waiter waiter;

    std::shared_ptr<FishFlavoredShreddedPorkCmd> ffspc = std::make_shared<FishFlavoredShreddedPorkCmd>(chef.get());
    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;
}

 

  • 运行结果

鱼香肉丝

宫保鸡丁

大盘鸡

优点

命令模式的优点

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

缺点

模式的缺点

如果命令很多,Command类会很多,增加系统复杂性。

总结

参考来自:https://www.cnblogs.com/xuwendong/p/9814421.html

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

命令模式主要解决的问题是在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合,这是命令模式的使用场景

如果系统支持命令的撤销和恢复的话,可以考虑使用命令模式

命令模式的实现过程通过调用者调用 接受者执行命令,顺序:调用者→接受者→命令。

 

 
上一篇:SQL Server通过外部程序集注册正则表达式函数(CLR函数) [转]


下一篇:命令模式,阿里P8面试官都说太详细了