设计模式---命令模式(C++实现)

版权声明:本文为博主原创文章,转载需标明出处。 https://blog.csdn.net/My_heart_/article/details/62436730

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适 的对象,并把该命令传给相应的对象,该对象执行命令。


意图

将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。

解决问题

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


如何解决

        通过调用者调用接受者执行命令,顺序:调用者->接受者->命令


优点

        1.降低了系统耦合度

        2.新的命令可以很容易添加到系统中

缺点 

         使用命令模式可能导致有些系统有过多的具体命令类


使用场景

         认为命令的地方都可以使用命令模式的,比如:GUI中每一个按钮都是一个命令;模拟CMD命令

注意事项

         系统需要支持命令的撤销(Undo)和恢复(Redo)操作也可以使用命令模式。



C++实现


举例

         我们都经历过以前在火车站买票的场景吧(通宵排队买票),但是现在呢,基本上很少出现这样的情况了吧,因为有了12306。12306刚出来的时候,每次买票就是不停的在电脑面前点击鼠标刷票,那个时候12306还是很脆弱,一票难求啊;现在好了,慢慢强大的12306,买票时出现了一个排队系统,先买票,进入12306派对系统;然后系统一个一个处理大家的请求,一旦你的购票请求进入了排队系统,那么你就无法再次进行刷票了,除非你退出排队系统。这就减少了购票者的刷票次数;减少了12306后台服务器的处理压力。那么,你有没有想过,12306是如何将你的购票请求加入排队系统的呢?这样的排队系统是如何实现的呢?那就是使用了命令模式。


         我们在12306上,单击购票,这是个请求,12306把这个请求封装为一个对象,12306还没有上线排队系统,买票是这样的:你不停的用鼠标点击12306网站上的购票按钮,直到你买到了票;对于你的每一次点击,服务器都要进行处理,做出响应,告诉你,有没有买到票;这样,可能就会出现很多次无效的点击,但是这些无效的点击却增加了服务器的负担。  增加了排队系统之后:你的购票请求就进入了对应的购票队列,一旦你进入了购票队列,当你再次鼠标单击购票时,12306会拒绝你的购票请求,它会告诉你,你已经进入了购票队列;处于购票队列中的你,你可以选择退出购票队列去购买其它车次的车票,从而进入其它购票队列。这样就有效的减少了购票者发送很多无效的购票请求。

         这就好比票是共享资源,谁都想要,但票数是固定的;在没有排队系统之前,大家的购票请求都是去竞争这个票,服务器对于大家对于共享资源——票的竞争进行互斥,谁抢到了,票就少一张;而现在有了购票队列以后,大家都不用去竞争了,按时间的先后顺序排好队,12306把票一张张的发给进入队列的购票者。


UML类图



code:

//命令模式
/*
	Command:声明执行操作的接口;
	ConcreteCommand:将一个接收者对象绑定于一个动作,之后,调用接收者相应的操作,以实现Execute来完成相应的命令;
	Client:创建一个具体命令对象,但是并没有设定它的接收者;
	Invoker:要求该命令执行这个请求;
	Receiver:知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者。

	//按照下面的方式协作:
	1.Client创建一个ConcreteCommand命令对象,并指定它的Receiver对象;
	2.Invoker对象存储该ConcreteCommand对象;
	3.该Invoker通过调用Command对象的Execute操作来提交一个请求。如果这个命令请求是可以撤销的,ConcreteCommand就执行Execute操作之前存储当前状态以用于取消该命令请求;
	4.ConcreteCommand对象调用Receiver的一些操作以执行该请求。
*/
class Receiver
{
public :
	void Action()
	{
		cout <<"Receiver -> Action" << endl;
	}
};
class Command
{
public :
	virtual void Execute() = 0;
};

class ConcreteCommand : public Command
{
public:

	ConcreteCommand(Receiver *pReceiver)
	:m_pReceiver(pReceiver)
	{}
	void Execute()
	{
		m_pReceiver->Action();
	}
private:
	Receiver * m_pReceiver;
};

class Invoker
{
public:
	Invoker(Command * pCommand)
		:m_pCommand(pCommand)
	{}
	void Invoke()
	{
		m_pCommand->Execute();
	}
private:
	Command * m_pCommand;
};


客户端:


int test_Command()//命令模式
{
	Receiver* pReceiver = new Receiver();//请求
	Command* pCommand = new ConcreteCommand(pReceiver);//把请求绑定为对象
	Invoker* pInvoker = new Invoker(pCommand); //要求该命令执行这个请求
	pInvoker->Invoke(); //执行!
	delete pReceiver;
	delete pCommand;
	delete pInvoker;

	system("pause");
	return  0;
}

总结

命令模式是一个很经典的模式,在我们身边有很多例子,比如:数据库中的事务就是使用命令模式,C#的委托使用的也是命令模式。


参考:

       果冻想::::    http://www.jb51.net/article/55963.htm


猜你喜欢

转载自blog.csdn.net/My_heart_/article/details/62436730