撤消如何工作?

时间:2010-06-10 15:57:27

标签: objective-c language-agnostic design-patterns oop

undo如何运作?每次任何值更改时,它是否复制所有托管对象?或者它是否仅将实际更改与对象受影响的信息一起复制?是重型还是轻量级?

2 个答案:

答案 0 :(得分:2)

几乎任何支持面向对象构造的语言的“撤销”机制都使用Memento Design Pattern来实现它。

答案 1 :(得分:1)

这是一个让你思考的粗略实现。这将处理您的可撤消操作堆栈。 (它不处理重做,但通过用列表替换堆栈并跟踪当前项目,可以很容易地支持重做。)

public class Undoable {
    public static void Do(Action do, Action undo) {
        do();
        sUndoStack.Push(new Undoable(do, undo));
    }

    public static void Undo() {
        sUndoStack.Pop().mUndoCallback();
    }

    private Undoable(Action doCallback, undoCallback) {
        mDoCallback = doCallback;
        mUndoCallback = undoCallback;
    }

    private Action mDoCallback, mUndoCallback;

    // note: using a global stack here is lame, but works for demo purposes
    private static readonly Stack<Undoable> sUndoStack = new Stack<Undoable>();
}

要使用它,假设用户可以更改某个对象中的值,如下所示:

public class Foo {
    public string Bar {
        get { return mBar; }
        set {
            if (mBar != value) {
                mBar = value;
            }
        }
    }

    private string mBar;
}

要使该操作可撤消,我们只需将setter更改为:

set {
    if (mBar != value) {
        string oldValue = mBar;
        Undoable.Do(() => mBar = value,
                    () => mBar = oldValue);
    }
}

现在,如果您从应用程序的任何位置调用Undoable.Undo(),您的Foo实例将恢复之前的Bar值。如果Foo也在Bar更改时引发事件(此处未显示),则UI也将在撤消时正确刷新。