在 JComponent 上具有 UndoManager 和 Listeners 时的 OO 概念

OO Conception when having UndoManager and Listeners on a JComponent

在 Swing 中构建 GUI 时,我总是遇到一个概念问题,即我以糟糕的方式结束了黑客攻击。我想知道关于它的好的做法。

举个简单的例子

我有一个 JComponent,我想在其上实现 undo/redo 操作,以及一些 add/remove 其他组件的操作。所以,我会开始写作:

public class MyComponent extends JComponent {
    private UndoManager undo =  new UndoManager();
    public void addComponent(JComponent comp) {
        this.add(comp);//Add the component to the view
        undo.addEdit(new ComponentAddedEdit(comp));//make this action undoable
        fireComponentAdded(comp);//warn the listeners that the action occured
    }
}

接下来开始做题。在我的 ComponentAddedEdit 中,我会想到类似的东西:

public class ComponentAddedEdit extends AbstractUndoableEdit {
    private final JComponent comp;
    public ComponentAddedEdit(JComponent comp) {this.comp = comp;}
    @Override
    public void undo() throws CannotUndoException {
        MyComponent.this.removeComponent(comp);
    }
    @Override
    public void redo() throws CannotRedoException {
        MyComponent.this.addComponent(comp);
    }
}

当然,它不起作用,因为重做操作将创建一个新的 Edit 到 UndoManager。所以我需要创建一个这样的新方法:

public void addComponentNoUndo() {
        this.add(comp);//Add the component to the view
        fireComponentAdded(comp);//warn the listeners that the action occured
}

最后,仅针对 "add" 操作,我得到了 3 个名称相似的方法:addaddComponentaddComponentNoUndo。如果我有更多的动作,更复杂的动作,它会变得非常混乱。那你会怎么做呢?

我不是很喜欢摇摆,所以我可能不会给你一个具体的实现答案,但是看到这个tutorial on memento pattern

您当然需要根据自己的需要进行调整,但我认为这是正确的方法。

尝试编写您自己的 "state"-class 而不是简单地使用字符串。

然后你想撤消一些东西,加载旧状态。如果您不希望用户能够撤消某些操作,只需不要加载以前的状态,告诉用户这是不可能的。考虑将布尔标志 "undoable" 添加到 "state"-class.

编辑

类似

class state extends JComponent {

   private boolean undoable;
   private JComponent toSave;

   public state (boolean undoable, JComponent toSave, ...) {
      this.undoable = undoable;
      this.toSave = toSave;
      ...
   }
...
}