Я занимаюсь разработкой редактора для некоторой бинарной древовидной структуры, и мне нужно иметь функцию отмены. Я думал об использовании шаблона команды для достижения этой цели. Однако я все еще не смог найти способ использовать шаблон команды с моей двоичной древовидной структурой.
Бинарная древовидная структура состоит из указателей. Таким образом, узел знает своего родителя и своих потомков. Когда я теперь хочу добавить узел, я бы построить NodeAdd
объект с родителем в качестве параметра и передать его UndoStack
, Чтобы удалить существующий узел NodeRemove
объект будет передан UndoStack
с указателем на Node
в качестве параметра. Оба, NodeAdd
а также NodeRemove
придется реализовать undo()
а также redo()
(где redo()
вызывается, когда объект помещен на UndoStack
).
Проблема, с которой я сталкиваюсь, связана с ситуацией, когда удаление узла, а затем добавление этого же узла должно быть отменено:
Однажды повторить NodeRemove выполняется Node
Объект уничтожен. в отменить NodeRemove новый Node
объект может быть построен снова, но отменить NodeAdd не может быть выполнен, так как у него нет указателя на вновь созданный Node
,
Я думаю, что я пытаюсь использовать шаблон команды неправильно. Я, вероятно, должен разрушить или построить Node
объекты скорее внутри конструктора / деструктора команд, чем внутри undo()
/redo()
, К сожалению, я понятия не имею, как это сделать с такой структурой, и все примеры и советы, которые я смог найти, связаны с редактированием текста или редактированием чего-либо, где у вас нет динамической структуры с указателями.
Есть идеи, как подойти к этой проблеме?
Одним из вариантов будет иметь ваш Command
объекты ссылаются на свои операнды по некоторому уникальному идентификатору (скажем, индекс представлен в виде size_t
) вместо адреса памяти, который, как вы обнаружили, может колебаться.
Затем, поддерживая unordered_map< size_t, Node* >
где-то (скажем, статический член Node
например) ваш Command
объекты могут получить текущее воплощение данного Node
и добавить / удалить / манипулировать им по мере необходимости.
Шаблон команды, вероятно, недостаточно для отмены. Для отмены, вы должны использовать шаблон памяти.
Узоры можно комбинировать даже внутри себя. Дайте своим командам и метод execute, и метод отмены. Когда команда вызывается, поместите экземпляр в двухстороннюю цепочку ответственности, укажите направление и методы отмены и повтора.