结合命令和访客设计模式

问题描述 投票:0回答:1

在设计个人项目的架构时,我提出了使用这两种模式的组合来解决架构问题的想法。在 MVC 上下文中,我需要实现由 UI 触发的各种类型的操作。我想从执行逻辑中抽象出控制器,并由模型负责。问题是我有不同类型的命令,并且根据命令的类型,它应该通过程序的不同逻辑路径进行路由。因此,我不仅需要将要执行的操作委托给命令本身,还需要对其进行路由。

这是我想要实现的设计示例:

class ICommand {
public:
    virtual ~ICommand() {}
    virtual void execute() = 0;
    virtual void accept(CommandVisitor& visitor) = 0;
};

class CommandVisitor {
public:
    void visit(SaveFileCommand& command);
    void visit(SaveConfiguration& command);

    void visit(SaveFileCommand& command) {
        // logic
    }

    void visit(SaveConfiguration& command) {
        // logic
    }
};

class SaveFileCommand : public ICommand {
public:
    void execute() override {
        // logic
    }
    void accept(CommandVisitor& visitor) override {
        visitor.visit(*this);
    }
};

class SaveConfiguration : public ICommand {
public:
    void execute() override {
        // logic
    }
    void accept(CommandVisitor& visitor) override {
        visitor.visit(*this);
    }
};

我担心的是创建一个过于复杂的设计,我不确定这是否是解决我的问题的最佳方法。除此之外我还有什么选择?

c++ architecture visitor-pattern command-pattern
1个回答
0
投票

划出一些示例命令来指导您的架构方向是个好主意。纯粹基于“SaveFileCommand”和“SaveConfigurationCommand”,我发现自己想知道您是否希望所有命令都像这些一样不变,或者其他命令是否会包含会改变您的内部状态的内容?这是一个关键的决策点,因为确定一组更具代表性的命令将极大地帮助您了解架构。例如:

  1. 如果您有修改 UI 状态的命令,您可能希望将这些命令添加到“撤消”堆栈中,因此可能希望有一个与 CommandVisitor 分开的第二个命令处理程序,它管理命令堆栈。
  2. 如果您有需要访问外部进程的命令,您可能需要一个命令处理程序,它将异步调用卸载到线程或线程池以异步管理此类操作。对于 SaveFileCommand 和 SaveConfigurationCommand 来说也是如此,它们的处理范围可能会扩大,需要证明卸载繁重的 I/O 工作是合理的。
  3. 如果命令包含大量高频操作的类型,例如修改大量内存数据存储的元素,则出于性能考虑,您可能会喜欢希望跳过任何虚拟调用或动态内存的命令处理程序。
  4. 您甚至可能会问是否存在可能影响 CommandVisitor 本身的处理行为的命令:CommandVisitor 是否会保留其自己的可能被修改的状态?什么样的命令可以定义此类操作?

我的强烈建议是继续写出您期望使用的命令,并在执行此操作时写出 CommandVisitor。为此,请利用单元测试来查看编写新命令或扩展 CommandVisitor 的体验,以及您是否发现可能需要将 CommandVisitor 分解为众多“命令处理程序”的摩擦。

如果您有兴趣阅读该领域的更多内容,您可以查看 Qt 的 QUndoCommand 架构,以获取在 GUI 中管理命令的灵感,或者查看任意数量的消息总线系统(例如 Kafka 或 Aeron)来管理系统之间的命令流。

如果您正在寻找更多特定于 C++ 的结构来帮助定义命令,我喜欢 Jarod42 的建议,即考虑 std::variant,因为它可以是对命令处理程序支持的命令组进行建模的好方法,而无需要求他们共享一个对象层次结构。我自己在类似的情况下也发现了很好的效果。

© www.soinside.com 2019 - 2024. All rights reserved.