命令模式(Command Pattern)
将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。对请求排队或记录请求日志,以支持可撤销的操作
主要解决:
在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。
何时使用:在某些场合,比如要对行为进行”记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将”行为请求者”与”行为实现者”解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
如何解决:通过调用者调用接受者执行命令,顺序:调用者→接受者→命令。
关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口
应用实例:
struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的Command。
优点:
1、降低了系统耦合度。
2、新的命令可以很容易添加到系统中去。
3、系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,可以使用命令模式
缺点:
使用命令模式可能会导致某些系统有过多的具体命令类。
使用场景:
认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。
实例
在上学那会, 班长一般都充当了学生和老师之间的桥梁,什么时候上课由班长来通知,作业也由班长来通知, 但是真正的执行者是老师,上课是老师决定的,下课是老师决定的,班长其一个通知的作用,这相当与于一个一个的命令,由班长传达, 老师执行, 下面我们就通过了命令模式实现了这个过程。
#include <iostream>
#include "commandmode.h"
int main(int argc, char *argv[])
{
//老师
Teacher *teacher = new Teacher;
//定义老师可执行的事务
Command *attendClass = new AttendClassCommand(teacher);
Command *finishClass = new FinishClassCommand(teacher);
Command *receiverHomework = new ReceiverHomework(teacher);
//班长
Monitor *monitor = new Monitor;
//给班长增加职责
monitor->addCommand(attendClass);
monitor->addCommand(finishClass);
monitor->addCommand(receiverHomework);
monitor->undoCommand(finishClass);
//班长通知后, 老师开始执行
monitor->notify();
return 0;
}
#ifndef COMMANDMODE_H
#define COMMANDMODE_H
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
using std::cout;
using std::endl;
class Teacher
{
public:
Teacher(){}
/**
* @brief attendClass
* 执行上课这个行为
*/
void attendClass()
{
cout << "Teacher: attend class now" << endl;
}
/**
* @brief finseClass
* 时间到,老师执行下课这个行为
*/
void finishClass()
{
cout << "Teacher: finsh class now" << endl;
}
/**
* @brief receiverHomework
* 老师,收家庭作业
*/
void receiverHomework()
{
cout << "Teacher: receiver homework now" << endl;
}
};
/**
* @brief The Command class
* 所有的具体命令都实现Commmand这个抽象类,其中命令和命令的执行者是依赖的关系
* Teacher 是命令的执行者
*/
class Teacher;
class Command
{
public:
Command(Teacher *teacher): teacher(teacher){}
virtual void exec(){}
protected:
Teacher *teacher;
};
class AttendClassCommand : public Command
{
public:
AttendClassCommand(Teacher *teacher): Command(teacher){}
void exec()
{
teacher->attendClass();
}
};
class FinishClassCommand : public Command
{
public:
FinishClassCommand(Teacher *teacher): Command(teacher){}
void exec()
{
teacher->finishClass();
}
};
class ReceiverHomework : public Command
{
public:
ReceiverHomework(Teacher *teacher): Command(teacher){}
void exec()
{
teacher->receiverHomework();
}
};
/**
* @brief The Monitor class
* 这个类负起通知作用, 同学上课有班长通知,收作业也是由班长通知
*/
class Monitor
{
public:
Monitor(){}
/**
* @brief Notify
* 通知执行命令
*/
void notify()
{
for(Command * cmd: commandList)
{
cmd->exec();
}
}
/**
* @brief addCommand
* @param cmd
* 增加职责
*/
void addCommand(Command *cmd)
{
commandList.push_back(cmd);
}
/**
* @brief undoCommand
* @param cmd
* 撤销命令
*/
void undoCommand(Command *cmd)
{
for (auto iter=commandList.begin();
iter!=commandList.end();
iter++)
{
if (*iter == cmd)
{
commandList.erase(iter);
return ; //删除其中一个元素后,迭代器失效
}
}
}
private:
list<Command *> commandList;
};
#endif // COMMANDMODE_H