|
|
@@ -0,0 +1,178 @@
|
|
|
+#ifndef __COMMANDMODEL_H__
|
|
|
+#define __COMMANDMODEL_H__
|
|
|
+
|
|
|
+#include "spdlog/spdlog.h"
|
|
|
+
|
|
|
+#include <map>
|
|
|
+#include <list>
|
|
|
+
|
|
|
+/**
|
|
|
+ 命令模式
|
|
|
+ 定义:将一个请求封装为一个对象,从而使您可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
|
|
|
+ UML类图:
|
|
|
+ Client(客户端)
|
|
|
+ │
|
|
|
+ Invoker(调用者)
|
|
|
+ │
|
|
|
+ Command(抽象命令)
|
|
|
+ │
|
|
|
+ ┌───┴──────────┐
|
|
|
+ ConcreteCommandA ConcreteCommandB(具体命令)
|
|
|
+ │
|
|
|
+ Receiver(接收者)
|
|
|
+
|
|
|
+ 角色:
|
|
|
+ Command(命令接口):定义 execute() 方法,封装执行逻辑。
|
|
|
+ ConcreteCommand(具体命令):实现 Command,并持有 Receiver,调用其方法执行具体操作。
|
|
|
+ Receiver(接收者):实际执行操作的对象,提供具体的功能实现。
|
|
|
+ Invoker(调用者):持有 Command 对象,触发 execute(),可以支持命令队列、撤销等功能。
|
|
|
+ Client(客户端):创建 Command 对象,并将其传递给 Invoker。
|
|
|
+ 优点:
|
|
|
+ 1、降低了命令的发起者与命令的执行者之间的耦合度。
|
|
|
+ 2、新的命令可以很容易地加入到系统中。
|
|
|
+ 3、可以比较容易地设计一个命令队列和宏命令。
|
|
|
+ 4、可以方便地实现对请求的撤销和重做。
|
|
|
+ 缺点:
|
|
|
+ 1、使用命令模式可能会导致某些系统有过多的具体命令类。
|
|
|
+ 适用场景:
|
|
|
+ 1、系统需要将请求调用者与请求接收者解耦时。
|
|
|
+ 2、系统需要支持命令的撤销(Undo)和重做(Redo)操作时。
|
|
|
+ 3、系统需要将一组操作组合在一起,即支持宏命令(Macro Command)时。
|
|
|
+
|
|
|
+ 示例:
|
|
|
+ 使用命令模式实现只能家居
|
|
|
+ */
|
|
|
+
|
|
|
+namespace CommandModel {
|
|
|
+
|
|
|
+/* =========================================================
|
|
|
+ * 命令接收者,这里是设置,会有多个具体的接收者
|
|
|
+ * ========================================================= */
|
|
|
+
|
|
|
+/* 灯光 */
|
|
|
+class Light
|
|
|
+{
|
|
|
+public:
|
|
|
+ void on() {
|
|
|
+ SPDLOG_INFO("灯光已打开");
|
|
|
+ }
|
|
|
+ void off() {
|
|
|
+ SPDLOG_INFO("灯光已关闭");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+class TV
|
|
|
+{
|
|
|
+public:
|
|
|
+ void on() {
|
|
|
+ SPDLOG_INFO("电视已打开");
|
|
|
+ }
|
|
|
+ void off() {
|
|
|
+ SPDLOG_INFO("电视已关闭");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/* =========================================================
|
|
|
+ * 命令接口
|
|
|
+ * ========================================================= */
|
|
|
+/* 抽象命令 */
|
|
|
+class AbstractCommand
|
|
|
+{
|
|
|
+public:
|
|
|
+ virtual ~AbstractCommand() = default;
|
|
|
+ virtual void execute() = 0;
|
|
|
+ virtual void undo() = 0;
|
|
|
+};
|
|
|
+
|
|
|
+/* 开灯命令 */
|
|
|
+class LightOnCommand : public AbstractCommand
|
|
|
+{
|
|
|
+public:
|
|
|
+ LightOnCommand(Light* light) : m_light(light) {}
|
|
|
+ void execute() override {
|
|
|
+ m_light->on();
|
|
|
+ }
|
|
|
+ void undo() override {
|
|
|
+ m_light->off();
|
|
|
+ }
|
|
|
+private:
|
|
|
+ Light* m_light;
|
|
|
+};
|
|
|
+
|
|
|
+/* 关灯命令 */
|
|
|
+class LightOffCommand : public AbstractCommand
|
|
|
+{
|
|
|
+public:
|
|
|
+ LightOffCommand(Light* light) : m_light(light) {}
|
|
|
+ void execute() override {
|
|
|
+ m_light->off();
|
|
|
+ }
|
|
|
+ void undo() override {
|
|
|
+ m_light->on();
|
|
|
+ }
|
|
|
+private:
|
|
|
+ Light* m_light;
|
|
|
+};
|
|
|
+
|
|
|
+/* 开电视命令 */
|
|
|
+class TVOnCommand : public AbstractCommand
|
|
|
+{
|
|
|
+public:
|
|
|
+ TVOnCommand(TV* tv) : m_tv(tv) {}
|
|
|
+ void execute() override {
|
|
|
+ m_tv->on();
|
|
|
+ }
|
|
|
+ void undo() override {
|
|
|
+ m_tv->off();
|
|
|
+ }
|
|
|
+private:
|
|
|
+ TV* m_tv;
|
|
|
+};
|
|
|
+
|
|
|
+/* 关电视命令 */
|
|
|
+class TVOffCommand : public AbstractCommand
|
|
|
+{
|
|
|
+public:
|
|
|
+ TVOffCommand(TV* tv) : m_tv(tv) {}
|
|
|
+ void execute() override {
|
|
|
+ m_tv->off();
|
|
|
+ }
|
|
|
+ void undo() override {
|
|
|
+ m_tv->on();
|
|
|
+ }
|
|
|
+private:
|
|
|
+ TV* m_tv;
|
|
|
+};
|
|
|
+
|
|
|
+/* =========================================================
|
|
|
+ * 调用者,这里是遥控器,这个遥控器是万能遥控器,可以控制所有设备
|
|
|
+ * ========================================================= */
|
|
|
+
|
|
|
+/* 遥控器设备 */
|
|
|
+class RemoteControl
|
|
|
+{
|
|
|
+public:
|
|
|
+ /* 设置命令(添加命令) */
|
|
|
+ void setCommand(int slot, AbstractCommand* command);
|
|
|
+ /* 执行命令 */
|
|
|
+ void pressButton(int dev);
|
|
|
+ /* 撤销命令 */
|
|
|
+ void pressUndo(int dev, int count = 1);
|
|
|
+
|
|
|
+private:
|
|
|
+ /* 即将要执行的命令列表 */
|
|
|
+ std::map<int, std::list<AbstractCommand*>> m_commands;
|
|
|
+ /* 可撤销的命令(已执行过的) */
|
|
|
+ std::map<int, AbstractCommand*> m_undoCommands;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+/* 使用遥控器 */
|
|
|
+void useRemoteControl();
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+#endif /* __COMMANDMODEL_H__ */
|
|
|
+
|
|
|
+
|