【问题标题】:Command pattern with linked tree structure (using pointers)具有链接树结构的命令模式(使用指针)
【发布时间】:2012-10-26 13:37:11
【问题描述】:

我正在为某种二叉树结构开发一个编辑器,我需要一个撤消功能。我考虑过使用命令模式来实现这一点。但是,我还没有找到将命令模式与我的二叉树结构一起使用的方法。

二叉树结构是通过指针组成的。所以一个节点知道它的父节点和子节点。当我现在想添加一个节点时,我会构造一个以父节点为参数的NodeAdd 对象并将其传递给UndoStack。为了删除现有节点,NodeRemove 对象将被传递给UndoStack,并带有指向Node 的指针作为参数。 NodeAddNodeRemove 都必须实现 undo()redo()(当对象放在 UndoStack 上时会调用 redo())。

我面临的问题是,处理一个节点删除然后添加同一个节点应该被撤消的情况:

  1. 重做节点添加
  2. 重做节点删除
  3. 撤消节点删除
  4. 撤消节点添加

一旦执行 redo NodeRemoveNode 对象就会被销毁。在 undo NodeRemove 中可以再次构造一个新的 Node 对象,但是 undo NodeAdd 无法执行,因为它没有指向新构造的 Node 的指针.

我想我试图以错误的方式使用命令模式。我可能应该销毁或构造Node 对象,而不是在命令的构造函数/析构函数中,而不是在undo()/redo() 中。不幸的是,我不知道如何使用这种结构来做到这一点,而且我能找到的所有示例和建议都与文本编辑或编辑没有带有指针的动态结构的内容有关。

任何想法如何解决这个问题?

【问题讨论】:

    标签: c++ design-patterns undo-redo


    【解决方案1】:

    一种选择是让您的 Command 对象通过某个唯一标识符(例如表示为 size_t 的索引)而不是通过内存地址来引用它们的操作数,正如您所发现的那样,内存地址可能会波动。

    然后,通过在某处维护unordered_map< size_t, Node* >(例如Node 的静态成员),您的Command 对象可以获得给定Node 的当前实施例,并根据需要添加/删除/操作它.

    【讨论】:

    • 我同意这是一个选项。谢谢你的建议。
    【解决方案2】:

    命令模式可能不足以进行撤消。对于撤消,您应该使用 memento 模式。

    【讨论】:

    • 如果我理解备忘录模式,我需要为每个州保留图表的副本。使用命令模式我只会存储两个状态之间的实际变化。虽然创建整个图表的副本可以避免我所描述的问题,但我很好奇是否有办法解决这个问题并只跟踪更改。
    【解决方案3】:

    模式可以组合,甚至在它们内部。给你的命令一个执行方法和一个撤销方法。调用命令时,将实例放入双向责任链中,具有撤消和重做方向和方法。

    【讨论】:

    • 我不明白你想指出什么。将一个实例放入双向责任链到底是什么意思?到目前为止,我只认识命令模式的粗略解释。
    猜你喜欢
    • 2018-03-07
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多