C++设计模式——命令模式

1定义
将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求队列或者记录请求日志,可以提供命令的撤销和恢复功能

2类图
在这里插入图片描述

角色描述:

Receiver接受者角色,就是干活的码农,命令传递打这里就应该被执行。

Command命令角色,对命令额封装,所有命令声明在此

Invoker调用者角色,接受到命令并且执行命令

class Receiver

{

protected:

  Receiver();

public:

  virtual ~Receiver() = 0;

  virtual void doSomething()=0;

};

class ConcreteReceiver:public Receiver

{

public:

  void doSomething()

  {

    cout << "doSomething...."<<endl;  

  }

};

claas Command
{

protected:

  Command();

public:

  virtual ~Command() = 0;

  virtual void execute() = 0;

};

class ConcreteCommand:public Command

{

public:

  ConcreteCommand(Receiver* re)

    :_receiver(re)

  {}

  ~ConcreteCommand(){}

  void execute()

  {

    _receiver.doSomething();  

  }

protected:

  Receiver * _receiver;

};

class Invoke

{

private:

  Command * _cmd;

public:

  void setCommand(Command * cmd)

  {

    _cmd = cmd;

  }

  void action()

  {

    _cmd->execute();

  }
};

4应用
① 优点

类间解耦

可扩展性

结合其他模式更加优秀:结合责任链模式实现命令族解析任务;结合模板方法,减少Command子类的膨胀

②缺点

命令越多,类约膨胀,需要慎用

③使用场景

只要认为是命令的地方。eg GUI 开发,按钮,DOS命令模拟,触发反馈机制的处理等

5扩展
①当一个命令需要多个接收者/执行者时,可以在命令内set多个接受者,完成通力合作的问题

②反悔问题,这个就设计备忘录模式了。或者通过反向链式存储机制得到前次记录,实现回滚。rollback

注:在项目中,约定的优先级最高,每个命令都是对一个或者多个接受者的封装。在项目中可以通过有意义的命名来实现Client和Receiver间的依赖描述

6提升
可以将接受者在Command中进行封装以及默认的指定。从而命令的单一职责,与接受者无关 且 高层无需了解调用时的接受者是谁

7命令模式练习

#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>
#include <list>

using namespace std;
//命令的最终执行者
class Cooker
{
public:
	//烤串
	void makeChuaner() {
		cout << "烤串师傅进行了烤串" << endl;
	}

	//烤鸡翅
	void makeChicken() {
		cout << "烤串师傅进行了烤鸡翅" << endl;
	}
};
//烤串的  抽象的 菜单
class Command
{
public:
	Command(Cooker *cooker)
	{
		this->cooker = cooker;
	}
	~Command() {
		if (this->cooker != NULL) {
			delete this->cooker;
			this->cooker = NULL;
		}
	}

	//菜单让最终的执行者干活的方法
	virtual void execute() = 0;

protected:
	Cooker *cooker;
};

//烤串的菜单
class CommandChuaner :public Command
{
public:
	CommandChuaner(Cooker *cooker) : Command(cooker) {}

	virtual void execute()  {
		//命令 最终让执行者干的工作。
		this->cooker->makeChuaner();
	}
};

//烤鸡翅的菜单
class CommandChicken :public Command
{
public:
	CommandChicken(Cooker * cooker) : Command(cooker) {}

	virtual void execute() {
		//命令 最终让执行者干的工作。
		this->cooker->makeChicken();
	}
};
//管理所有命令的一个模块
//服务员MM
class Waitress
{
public:
	//给服务员添加菜单的方法
	void setCmd(Command *cmd)
	{
		this->cmd_list.push_back(cmd);
	}

	//让服务员mm 下单
	void notify() {
		list<Command *>::iterator it = cmd_list.begin();
		for (; it != cmd_list.end(); it++) {
			(*it)->execute(); //在此发生了多态
		}
	}
private:
	list<Command *> cmd_list;
};

int main(void)
{
	Waitress *mm = new Waitress;

	Command *chuanger = new CommandChuaner(new Cooker);
	Command *chicken = new CommandChicken(new Cooker);

	//把订单都给服务员
	mm->setCmd(chuanger);
	mm->setCmd(chicken);

	//让服务员下单,最终让师傅干活
	mm->notify();


	delete mm;
	
	return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_35718950/article/details/83927865