我负责维护使用Swing编写的旧应用程序,并结合使用Java3D编写的类似CAD的工具。我们在内存使用情况有问题。分析后,这与应用程序中的撤消功能有关。Swing/Java3D应用程序中基于状态的撤消:AOP解决方案?
所有取消的功能是基于状态的,有这样一个基本概念:创建这些UndoActions
public class UndoAction {
private UndoTarget target;
private Object old_data;
private Object new_data;
}
代码在整个应用程序基本上散落。因为有新的对象,现有对象的修改和子树的修改的修改之间没有区别,会发生以下情况:
会发生什么事是一个单一的动作如下:
- 创建一个新的对象
A
。 - 修改对象的字段
foo
。新的UndoAction被放置在包含foo_old和foo_new的堆栈中。 - 修改该对象的字段
bar
。新的UndoAction被放置在堆栈上,其中包含bar_old和bar_new。 - 执行
B.setField(A)
。新的UndoAction被放置在包含field_old和field_new(== A)的堆栈中。
根本没有粒度或任何控制。这根本无助于可维护性。
我想重构这个系统,使它变得可维护和内存友好。不幸的是,使用Command模式来实现Undo系统是不可能的。这些行为太影响回复。我想执行以下操作:
- 使用注释提供“撤消划界”。 @Undoable()会将一个方法标记为生成一个放在堆栈上的UndoAction。这可以像事务一样进行参数化:REQUIRE,NEST,JOIN ...在进入Undoable方法时克隆完整对象图。
- 当事务(=方法)完成时,算法应该将新状态与旧状态进行比较并保存差异。
- 要实现这一点,我们可以使用AOP。这使我们能够保持核心代码非常干净。
的现在,我的问题: 做任何上述3种功能的Java中已经存在?我可以想象,我不是第一个与基于状态的撤消和与之相关联的问题(撤消分界,状态比较,...)
AspectJ非常强大,这可能适用于你想要做的事情。 – jbranchaud 2012-01-05 15:48:13
当addFirst()超过某个限制时,不能使用Deque和removeLast()吗? – trashgod 2012-01-05 18:09:00
UndoStack的确切实现并不困难; Swing UndoManager对我来说很好。难点在于构建oldState和newState:克隆什么,何时将其添加到新的UndoAction以及如何确保旧数据不被引用。 – parasietje 2012-01-05 18:09:30