设计模式:命令模式 C++实现

本文介绍了命令模式的概念,通过买烤串的例子解释了其工作原理,实现了将请求者与执行者解耦。文章还提供了C++代码实现,包括烤肉串者、抽象命令、具体命令、服务员类,并展示了如何使用命令模式处理点餐和取消订单操作。最后,总结了命令模式的松耦合和扩展性优点。
摘要由CSDN通过智能技术生成


前言

今天复习了命令模式,感觉挺有意思的,这里跟大家分享下!


1. 命令模式理解

命令模式,就是将命令发出人与命令执行人分开,让它们不直接联系,而是通过第三者记录这些命令,然后再由这个第三者把这些命令告诉命令执行人去执行,这中间可以在以前命令的基础上新增或者删除命令,实现了松耦合。

《大话设计模式》中举了个很恰当的例子:买烤串的人和烤串的人。路边摊上买烤串的人都是直接告诉烤串者自己要什么,人多的话,容易出错。有了命令模式后,就相当于烤串者有了铺面,有了服务员,有了菜单,买烤串的人直接和服务员沟通,服务员将客户要求记录在菜单上,然后服务员将菜单通过厨房传递给烤串者,这样烤串者就可以按照这一张张菜单来烤串了,再也不用担心出错了,既方便计算账单,也方便客户退单等。

命令模式比较正规的定义与类图(引用《大话设计模式》)如下所示:
在这里插入图片描述
在这里插入图片描述
上述类图中,Client就等同于买烤串的人,Invoker就相当于服务员,Command就相当于菜单,上面记录了一条条客户点的串,Receiver就相当于做烤串的人,是不是很清晰明了!


2. 命令模式C++实现

这里以在店铺吃烤串为例实现命令模式,类图(引用《大话设计模式》)如下所示:
在这里插入图片描述
C++代码实现如下:

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <memory>
#include <list>
#include <chrono>

// 获取系统当前时间
std::string getCurrentSystemTime()
{
	auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
	struct tm* ptm = localtime(&tt);
	char date[60] = { 0 };
	sprintf(date, "%d-%02d-%02d-%02d.%02d.%02d",
		(int)ptm->tm_year + 1900, (int)ptm->tm_mon + 1, (int)ptm->tm_mday,
		(int)ptm->tm_hour, (int)ptm->tm_min, (int)ptm->tm_sec);
	return std::string(date);
}

//**************************Command Pattern*********************
//烤肉串者
class Barbecuer
{
public:
	void BakeMutton()
	{
		std::cout << "烤羊肉串!" << std::endl;
	}

	void BakeChickenWing()
	{
		std::cout << "烤鸡翅!" << std::endl;
	}
};

//抽象命令类
class Command
{
protected:
	std::shared_ptr<Barbecuer> smartBarbecuer;
	std::string strDescription;
public:
	Command(std::shared_ptr<Barbecuer> pBarbecuer, const std::string& strDesc): smartBarbecuer(pBarbecuer), strDescription(strDesc) {}

	virtual void ExecuteCommand() = 0;

	std::string GetDescription() const
	{
		return strDescription;
	}
};

//烤羊肉串命令
class BakeMuttonCommand : public Command
{
public:
	BakeMuttonCommand(std::shared_ptr<Barbecuer> receiver, const std::string& strDesc = "烤羊肉串"): Command(receiver, strDesc){}

	void ExecuteCommand()
	{
		smartBarbecuer->BakeMutton();
	}
};

//烤鸡翅串命令
class BakeChickenWingCommand : public Command
{
public:
	BakeChickenWingCommand(std::shared_ptr<Barbecuer> receiver, const std::string& strDesc = "烤鸡翅串") : Command(receiver, strDesc) {}

	void ExecuteCommand()
	{
		smartBarbecuer->BakeChickenWing();
	}
};

//服务员类
class Waiter
{
private:
	std::list<std::shared_ptr<Command>> orders;

public:
	void SetOrder(std::shared_ptr<Command> command)
	{
		if (command->GetDescription() == "烤鸡翅串")
		{
			std::cout << "服务员:鸡翅没有了,请点儿别的吧!" << std::endl;
		}
		else
		{
			orders.push_back(command);
			std::cout << "增加订单:" << command->GetDescription().c_str() << ", 时间:" << getCurrentSystemTime().c_str() << std::endl;
		}
	}

	void CancelOrder(std::shared_ptr<Command> command)
	{
		orders.remove(command);
		std::cout << "取消订单:" << command->GetDescription().c_str() << ", 时间: " << getCurrentSystemTime().c_str() << std::endl;
	}

	void Notify()
	{
		std::cout << "订单来了,厨房可以开始烤串了!" << std::endl;
		for (std::shared_ptr<Command> command : orders)
		{
			command->ExecuteCommand();
		}
	}
};

//****************************Test******************************
int main()
{
	//开店前准备
	std::shared_ptr<Barbecuer> boy = std::make_shared<Barbecuer>();
	std::shared_ptr<Command> bakeMuttonC1 = std::make_shared<BakeMuttonCommand>(boy);
	std::shared_ptr<Command> bakeMuttonC2 = std::make_shared<BakeMuttonCommand>(boy);
	std::shared_ptr<Command> bakeChickenWingC1 = std::make_shared<BakeChickenWingCommand>(boy);
	std::shared_ptr<Waiter> waiter = std::make_shared<Waiter>();

	//开始营业,顾客点菜
	waiter->SetOrder(bakeMuttonC1);
	waiter->SetOrder(bakeMuttonC2);
	waiter->SetOrder(bakeChickenWingC1);

	//点菜完毕,通知厨房
	waiter->Notify();

	//顾客取消订单
	waiter->CancelOrder(bakeMuttonC1);

	//点菜完毕,通知厨房
	waiter->Notify();

	system("pause");
	return 0;
}

总结

命令模式实现了请求者与实现者的分离,实现了松耦合,提高了扩展性。
个人感觉,命令模式是组合关系和事物抽象能力的应用产出的结果。事物抽象能力很重要,如果抽象能力运用的好,设计模式的运用就不是难事了!

参考

《大话设计模式》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值