前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++设计模式-命令模式讲解以文本编辑器为例

C++设计模式-命令模式讲解以文本编辑器为例

原创
作者头像
晨星成焰
修改2024-04-02 18:37:01
2121
修改2024-04-02 18:37:01
举报

命令模式简介

命令模式的核心思想是将请求封装为一个对象,这样就可以将请求者和接收者解耦,使得请求者不需要知道接收者的接口,只需要知道如何调用命令对象的执行方法。这样做的好处是可以将请求的发出者和接收者分离,使得它们可以独立地变化。这样也使得我们可以容易地支持请求的排队、记录请求日志以及支持可撤销的操作。

以简单的文本编辑器实现为例介绍命令模式

现有一个文本编辑器,在该文本编辑器中为客户提供了不同的对文本编辑的展示方式,有按钮型、菜单型,快捷键等。文本编辑主要包括新建文件、打开文件、保存文件等功能,根据客户在展示层的不同选择,该文本编辑器可实现不同的功能。请使用命令模式来模拟该问题的实现,要求绘制相应的类图并使用编程语言实现(扩展:模拟一个简单的服务器将命令请求封装成对象加入处理队列进行处理)

先用startuml画一个粗略的类图(画的不是很好)

类图
类图

再根据类图实现代码

代码语言:cpp
复制
#include<iostream>
#include<vector>
#include <Windows.h>
using namespace std;

class HandleClinetProtocal
{
public:

	void NewFile()
	{
		cout << "新建一个文件" << endl;
	}

	void OpenFile()
	{
		cout << "打开文件" << endl;
	}

	void SavaFile()
	{
		cout << "保存文件" << endl;
	}
};

class AbstractCommand {
public:
	virtual void run() = 0;
};

class NewFileCommand :public AbstractCommand {
public:
	NewFileCommand(HandleClinetProtocal* handle) {
		this->handle = handle;
	};
	void run() {
		this->handle->NewFile();
	}

	HandleClinetProtocal* handle;
};

class OpenFileCommand :public AbstractCommand {
public:
	OpenFileCommand(HandleClinetProtocal* handle) {
		this->handle = handle;
	};
	void run() {
		this->handle->OpenFile();
	}

	HandleClinetProtocal* handle;
};

class SaveFileCommand :public AbstractCommand {
public:
	SaveFileCommand(HandleClinetProtocal* handle) {
		this->handle = handle;
	};
	void run() {
		this->handle->SavaFile();
	}

	HandleClinetProtocal* handle;
};

//扩展:模拟服务器端实现命令
class Server
{
public:
	//将请求对象放入处理队列
	void addRequest(AbstractCommand* command)
	{
		mCommands.push_back(command);
	}

	//启动处理程序
	void startHandle()
	{
		if (mCommands.empty() == true) {
			cout << "cout error: no commands" << endl;
			exit(1);
		}
		while (!mCommands.empty())
		{
			Sleep(1000);
			AbstractCommand* command = mCommands.front();
			cout << "服务器接收到";
			command->run();
			mCommands.erase(mCommands.begin());
		}
	}
	vector<AbstractCommand*> mCommands;
};

void test01()
{
	HandleClinetProtocal* handle = new HandleClinetProtocal;
	Server* server = new Server;
	int k = 1;
	while (k >= 1 && k <= 3) {
		cout << "请选择一个按钮,1为新建文件,2为打开文件,3为保存文件,其他为退出程序开始运行命令" << endl;
		cin >> k;
		if (k == 1) {
			AbstractCommand* newfile = new NewFileCommand(handle);
			newfile->run();
			server->addRequest(newfile);
		}
		else if (k == 2) {
			AbstractCommand* openfile = new OpenFileCommand(handle);
			openfile->run();
			server->addRequest(openfile);
		}
		else if (k == 3) {
			AbstractCommand* savefile = new SaveFileCommand(handle);
			savefile->run();
			server->addRequest(savefile);
		}
		else {
			cout << "运行命令" << endl;
		}
	}
	//服务器开始处理请求
	server->startHandle();
}



int main() {
	test01();
	return 0;
}

代码解析:

  1. 在这段代码中,AbstractCommand是抽象命令类,它定义了run方法,这是命令执行的接口。
  2. NewFileCommand、OpenFileCommand和SaveFileCommand是具体命令类,它们继承了AbstractCommand,并实现了run方法。这些具体命令类封装了对HandleClinetProtocal对象的操作。
  3. Server类是调用者类,它包含了一个命令对象,并在startHandle方法中执行它。这个方法中,服务器从队列中取出命令对象并执行,这就是命令模式的一种实现方式。

命令模式的优缺点总结

命令模式的优点总结:

  • 解耦:命令模式将请求封装为对象,从而将请求者和接收者解耦。这意味着请求者不需要知道接收者的接口,只需要知道如何调用命令对象的执行方法。
  • 扩展性:命令模式使得添加新的命令非常容易。新的命令只需要实现命令接口,而不需要修改现有的代码。这满足了开闭原则,使得系统更容易扩展。

命令模式的缺点总结:

  • 过多的具体命令类:因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用3。
  • 高耦合度:虽然命令模式可以解耦请求者和接收者,但是它会在请求者和接收者之间引入新的耦合。具体来说,每个具体命令类都需要持有一个接收者,这意味着具体命令类和接收者之间存在耦合。

命令模式的应用场景

命令模式在实际应用中有许多常见的应用场景,以下是一些常见的例子:

GUI框架:在图形用户界面(GUI)框架中,命令模式常常用于实现按钮点击事件的处理。每个按钮点击事件都可以看作是一个命令,当按钮被点击时,就会执行相应的命令。

游戏开发:在游戏开发中,命令模式常常用于实现游戏的操作。例如,每个游戏操作(如移动、攻击等)都可以看作是一个命令,当玩家执行操作时,就会执行相应的命令。

事务管理:在事务管理中,命令模式常常用于实现撤销和重做操作。每个事务都可以看作是一个命令,当事务被执行时,就会执行相应的命令。如果需要撤销事务,就可以通过执行相反的命令来实现4。

宏命令:在需要执行一系列操作的场景中,可以使用命令模式。例如,在文本编辑器中,可以将一系列的格式化操作(如加粗、斜体等)封装为一个宏命令,这样就可以一次性执行多个操作。

最后是代码的运行展示和项目类视图

正常运行
正常运行
失败运行
失败运行
项目类视图
项目类视图

我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 命令模式简介
  • 以简单的文本编辑器实现为例介绍命令模式
    • 先用startuml画一个粗略的类图(画的不是很好)
      • 再根据类图实现代码
        • 代码解析:
          • 命令模式的优缺点总结
            • 命令模式的优点总结:
            • 命令模式的缺点总结:
          • 命令模式的应用场景
            • 最后是代码的运行展示和项目类视图
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
        http://www.vxiaotou.com