学以致用C++设计模式 之 “命令模式”

时间:2022-07-23
本文章向大家介绍学以致用C++设计模式 之 “命令模式”,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

团队管理者

前面说到我当程序员中介的经历,后来我就有点烦了,这客户有什么需求,都直接指名道姓找这个程序员那个程序员谈需求,我这会儿得给程序员A聊需求,过会儿得给程序员B聊需求,然后又得跟C说,跟D说,那怎么搞,客户不烦我都烦了。 后来,我决定了,我要把自己的权力扩大一点,有什么事儿直接和我说就够了,我去传达客户意思,这样客户也不用一个人面对那么多人,程序员们也可以不用抛头露面,多好。

这个案例中有哪些因素出现了呢? 首先是客户,不断提出需求修改的客户。 然后是我这个给程序员们下达命令的管理者。 接下来是负责UI的程序员A、负责后台的程序员B、负责需求分析的程序员C、D。 客户的需求,从直接传达到各个程序员,转移带传达给团队负责人,我,然后由我来统一调配。

那我们来画一下类图:

但是,仅仅通过一个字符串来传递信息,并不具备约束力,所以我们对类图进行如下修改:

解决方法是:对客户发出的命令进行封装,每个命令是一个对象,避免了客户和负责组员之间的交流误差。 Command抽象类只有一个方法,其作用就是用来执行命令,而项目组长类主要用来将命令解析执行。

其中,Command抽象类是整个扩展的核心。

代码实现

#include<iostream>

using namespace std;

//需求抽象类
class abstractXQ {
public:
	virtual void find() = 0;	//找到对应程序员
	virtual void add() = 0;		//新增任务
	virtual void del() = 0;		//删除任务
	virtual void change() = 0;	//修改任务
	virtual void show() = 0;	//发布代码
};

//UI程序员
class UI :public abstractXQ {
public:
	void find() { cout << "找到UI程序员" << endl; }
	void add() { cout << "新增UI界面" << endl; }
	void del() { cout << "UI界面删除" << endl; }
	void change() { cout << "UI界面修改" << endl; }
	void show() { cout << "UI代码发布" << endl; }
};

//后端
class BK :public abstractXQ {
public:
	void find() { cout << "找到后端程序员" << endl; }
	void add() { cout << "新增后端功能" << endl; }
	void del() { cout << "后端功能下架" << endl; }
	void change() { cout << "后端功能修改" << endl; }
	void show() { cout << "后端代码发布" << endl; }
};

//需求
class XQ :public abstractXQ {
public:
	void find() { cout << "找到需求分析" << endl; }
	void add() { cout << "新增需求" << endl; }
	void del() { cout << "需求删减" << endl; }
	void change() { cout << "需求修改" << endl; }
	void show() { cout << "需求分析发布" << endl; }
};

//任务调度基类
class Command {
protected:
	//我想知道,这个保护数据的意义在哪里?
	//公有继承的子类不是照样用吗?
	UI* ui = new UI();
	BK* bk = new BK();
	XQ* xq = new XQ();

public:
	virtual void execute() = 0;
};

//增加需求
class add_XQ :public Command {	//使用保护继承,会导致子类无法转换为父类对象
	void execute(){
		xq->find();
		xq->add();
		xq->show();
	}
};

//删除界面
class del_UI :public Command {
	void execute() {
		ui->find();
		ui->del();
		ui->show();
	}
};

//项目组长
class master {
private:
	Command* command;
public:
	void set_Comment(Command* c) { this->command = c; }
	void get_order() { this->command->execute(); }
};

//客户端类
int main()
{
	master* m = new master();
	Command* c1 = new add_XQ();
	Command* c2 = new del_UI();
	m->set_Comment(c1);
	m->get_order();

	m->set_Comment(c2);
	m->get_order();
	return 0;
}

感悟

怎么说呢?其实这个拓展性说不好他也确实一般般,你看,Command上层,要是加一个类,就得修改Command,要加新命令,又得修改Command下层,两头要修改。 我觉得与其这样,那为啥不考虑一下模板、工厂、建造者,反正都是写死的。

当然,也是有它的闪光点的,不过这些模式相似度也太高了。不好好捋清楚还真不好用。

命令模式

命令模式是个高内聚的模式! 将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者纪录请求日志,可以提供命令的撤销和恢复功能。 有兴趣自己去加一下这两个功能,或者去我上一个系列的命令模式里面去找也有。 学以致用,马上用!!

学以致用

命令模式的优点

  • 类间解耦 调用者角色和接受者角色之间没有任何依赖关系,调用者实现功能的时候只需要调用Command抽象类的execute方法就可以,不需要了解是哪个接受者在执行。
  • 可拓展性 Command
  • 命令模式与其他模式结合会更加优秀 命令模式可以结合责任链模式,实现命令模式族解析任务;结合模板方法模式,可以减少command子类膨胀的问题。

命令模式的缺点

Command会膨胀。

用武之地

你觉得哪里能用那就能用。

今天就到这里,请期待:下一篇“责任链模式”