2010-06-10 18 views
5

Jak działa undo? Czy kopiuje wszystkie zarządzane obiekty za każdym razem, gdy zmieni się dowolna z wartości? Czy też kopiuje tylko rzeczywiste zmiany wraz z informacją, które obiekty zostały dotknięte? Czy to jest ciężkie czy lekkie?Jak działa funkcja cofania?

Odpowiedz

2

Mechanizm "cofnij" dla prawie każdego języka, który obsługuje konstrukty zorientowane obiektowo, wykorzystuje Memento Design Pattern, aby to umożliwić.

+0

To niekoniecznie musi być prawda. Memento może spalić dużo pamięci. Aplikacje, nad którymi pracowałem, zazwyczaj używają wzorca polecenia, w którym każde polecenie zawiera logikę, aby wykonać zmianę i ją cofnąć. W ten sposób wydajesz tylko pamięć na różnicę między poprzednim i następnym stanem obiektu. – munificent

1

Oto przybliżona implementacja, która pomoże Ci myśleć. Zajmuje się stosem nieprzystosowanych operacji. (To nie obsługuje przerobić, ale to jest łatwe do obsługi przez zastąpienie stosu z listą i śledzenie aktualnej pozycji).

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>(); 
} 

Aby to wykorzystać, powiedzmy, że użytkownik może zmienić wartość w niektórych obiekt tak:

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

    private string mBar; 
} 

Aby operacja cofnąć, po prostu zmienić setter do:

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

teraz, jeśli zadzwonisz Undoable.Undo() z dowolnego miejsca w aplikacji, swoje wystąpienie Foo woli przywrócić poprzednią wartość paska. Jeśli Foo również podnosi zdarzenie, gdy pasek się zmienia (nie pokazano tutaj), interfejs będzie również poprawnie odświeżał się po cofnięciu.