Pregunta

I like to have a pattern for switching a feature, which at my case is Undo / Redo. I don't want a pattern for Undo/Redo. This is working fine. But a good way to skip the lines of code, that Undo / Redo requires. Example using undo:

AddItemToList(object item)
{
   Memento m = new Memento(..) // create application state object
   m_list.Add(item);
   m.AddState("item added", item); // store state change
   m_Caretaker.Add(m); // store state object
}

example without undo:

AddItemToList(object item)
{
   m_list.Add(item);
}

I like to have a pattern that is more elegant than this:

AddItemToList(object item)
{
    Memento m = null;
    if(m_UndoEnabled)
    {
        m = new Memento(..) // create application state object
    }
    m_list.Add(item);
    if(m_UndoEnabled)
    {
        m.AddState("item added", item); // store state change
        m_Caretaker.Add(m); // store state object
    }
}

Reason why I think it's not elegant: I would have to use the booelan flag twice, in each function that should support Undo/Redo.

¿Fue útil?

Solución

Why not use a Decorator? That way, suppose you have something called, e.g. EditQueue that you simply push the state changes into. You make an interface for that and then provide two implementations, one simply EditQueueImpl and the other UndoEnabledEditQueueImpl. The second would be a Decorator that had an instance of the EditQueueImpl inside and it would mean users of the class would not have to know anything about whether undo was turned on or not.

Otros consejos

I think a good way to implement this might be to use an the abstract factory pattern with some inheritance.

The abstract factory returns a concrete factory that either builds the real memento objects or a dummy memento. The dummy memento obviously doesn't do anything and works in a similar way as a null object.

In this way you'll have the flag in one place and use it just once (in the abstract factory). I've used and I use this approach and I find it quite elegant and simple (I might be biased :).

The not-so negative point, is that you need to inject either the abstract factory or the concrete factory in all methods or classes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top