Browse Source

V1.1.3
1、设计模式新增了命令模式示例

Apple 3 days ago
parent
commit
f7c8293b72

+ 2 - 2
CMakeLists.txt

@@ -188,13 +188,13 @@ file(GLOB GLOBAL_SRC
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/mqtt)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/mqtt)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/http)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/http)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/threadPool)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/threadPool)
-add_subdirectory(${CMAKE_SOURCE_DIR}/demo/ftp)
+# add_subdirectory(${CMAKE_SOURCE_DIR}/demo/ftp)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/OneThread)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/OneThread)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/timer)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/timer)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/time)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/time)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/VideoPlayer)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/VideoPlayer)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/xlsx)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/xlsx)
-# add_subdirectory(${CMAKE_SOURCE_DIR}/demo/DesignerPattern)
+add_subdirectory(${CMAKE_SOURCE_DIR}/demo/DesignerPattern)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/ViewModel)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/ViewModel)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/VideoPlayerGL)
 # add_subdirectory(${CMAKE_SOURCE_DIR}/demo/VideoPlayerGL)
 
 

+ 1 - 1
External

@@ -1 +1 @@
-Subproject commit f3046206216765a1e010ad9655535899826ad67e
+Subproject commit d2f5efa0dec7f5174e99644f6bf04300211cee3b

+ 2 - 1
demo/DesignerPattern/CMakeLists.txt

@@ -16,7 +16,7 @@ file(GLOB LOCAL_SRC
     ${CMAKE_CURRENT_SOURCE_DIR}/Iterator/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/Iterator/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/FlyWeight/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/FlyWeight/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/Combination/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/Combination/*.cpp
-
+    ${CMAKE_CURRENT_SOURCE_DIR}/CommandModel/*.cpp
 )
 )
 
 
 
 
@@ -43,6 +43,7 @@ target_include_directories(${this_exe} PRIVATE
     ${CMAKE_CURRENT_SOURCE_DIR}/Iterator
     ${CMAKE_CURRENT_SOURCE_DIR}/Iterator
     ${CMAKE_CURRENT_SOURCE_DIR}/Iterator/RingQueue
     ${CMAKE_CURRENT_SOURCE_DIR}/Iterator/RingQueue
     ${CMAKE_CURRENT_SOURCE_DIR}/Combination
     ${CMAKE_CURRENT_SOURCE_DIR}/Combination
+    ${CMAKE_CURRENT_SOURCE_DIR}/CommandModel
 )
 )
 
 
 target_link_libraries(${this_exe} PRIVATE
 target_link_libraries(${this_exe} PRIVATE

+ 85 - 0
demo/DesignerPattern/CommandModel/CommandModel.cpp

@@ -0,0 +1,85 @@
+#include "CommandModel.h"
+
+
+
+
+
+/* 设置命令 */
+void CommandModel::RemoteControl::setCommand(int slot, AbstractCommand* command) 
+{
+    m_commands[slot].push_back(command);
+    m_undoCommands[slot] = nullptr;
+}
+
+/* 执行命令 */
+void CommandModel::RemoteControl::pressButton(int dev) 
+{
+    if(m_commands[dev].empty()) 
+    {
+        SPDLOG_WARN("设备:{} 没有任何命令设置", dev);
+        return;
+    }
+    if (m_commands.find(dev) != m_commands.end()) 
+    {
+        AbstractCommand* command = m_commands[dev].front();
+        command->execute();
+        m_undoCommands[dev] = command;
+        m_commands[dev].pop_front();
+    } else {
+        SPDLOG_WARN("设备 {} 没有命令设置", dev);
+    }
+}
+
+/* 撤销命令 */
+void CommandModel::RemoteControl::pressUndo(int dev, int count) 
+{
+    if(m_undoCommands[dev] == nullptr)
+    {
+        SPDLOG_WARN("设备 {} 没有可撤销的命令", dev);
+        return;
+    }
+
+    if (m_undoCommands.find(dev) != m_undoCommands.end()) 
+    {
+        m_undoCommands[dev]->undo();
+        m_undoCommands[dev] = nullptr;
+    } else {
+        SPDLOG_WARN("设备 {} 没有可撤销的命令", dev);
+    }
+}
+
+
+/* 使用遥控器 */
+void CommandModel::useRemoteControl()
+{
+    /* 创建设备 */
+    Light* light = new Light();
+    TV* tv = new TV();
+
+    /* 创建命令 */
+    AbstractCommand* lightOnCommand = new LightOnCommand(light);
+    AbstractCommand* lightOffCommand = new LightOffCommand(light);
+    AbstractCommand* tvOnCommand = new TVOnCommand(tv);
+    AbstractCommand* tvOffCommand = new TVOffCommand(tv);
+
+    /* 创建遥控器 */
+    RemoteControl remote;
+    SPDLOG_INFO("按下按钮,打开灯光...");
+    remote.setCommand(1, lightOnCommand);
+    remote.pressButton(1);
+    SPDLOG_INFO("按下按钮,关闭灯光...");
+    remote.setCommand(1, lightOffCommand);
+    remote.pressButton(1);
+    SPDLOG_INFO("撤销上一个操作...");
+    remote.pressUndo(1);
+
+    SPDLOG_INFO("按下按钮,打开电视...");
+    remote.setCommand(2, tvOnCommand);
+    remote.pressButton(2);
+    SPDLOG_INFO("按下按钮,关闭电视...");
+    remote.setCommand(2, tvOffCommand);
+    remote.pressButton(2);
+    SPDLOG_INFO("撤销上一个操作...");
+    remote.pressUndo(2);
+}
+

+ 178 - 0
demo/DesignerPattern/CommandModel/CommandModel.h

@@ -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__ */
+
+

+ 3 - 1
demo/DesignerPattern/main.cpp

@@ -10,6 +10,7 @@
 #include "Adapter/Adapter.h"
 #include "Adapter/Adapter.h"
 #include "Iterator/IteratorDemo.h"
 #include "Iterator/IteratorDemo.h"
 #include "FlyWeight/FlyWeifht.h"
 #include "FlyWeight/FlyWeifht.h"
+#include "CommandModel/CommandModel.h"
 
 
 
 
 int main(int argc, char *argv[])
 int main(int argc, char *argv[])
@@ -51,8 +52,9 @@ int main(int argc, char *argv[])
 
 
     // testRingQueueManualMutex();
     // testRingQueueManualMutex();
 
 
-    testFlyWeight();
+    // testFlyWeight();
 
 
+    CommandModel::useRemoteControl();
 
 
     return a.exec();
     return a.exec();
 }
 }