用于“切换应用程序特征”的模式,例如撤销重做

时间:2012-11-15 14:02:53

标签: design-patterns undo-redo

我喜欢使用切换功能的模式,在我的情况下是Undo / Redo。 我不想要Undo / Redo的模式。这工作正常。 但是跳过代码行的好方法,Undo / Redo需要。 使用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
}

没有撤消的例子:

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

我喜欢有一种比这更优雅的图案:

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
    }
}

我觉得它不优雅的原因: 我必须在每个应该支持Undo / Redo的函数中使用booelan标志两次。

2 个答案:

答案 0 :(得分:0)

我认为实现这个的好方法可能是使用带有一些继承的抽象工厂模式。

抽象工厂返回一个具体的工厂,可以建造真正的纪念品或虚拟纪念品。虚拟纪念品显然没有做任何事情,并且以与空对象类似的方式工作。

通过这种方式,你可以在一个地方拥有旗帜并只使用一次(在抽象工厂中)。我已经习惯了,我使用这种方法,我发现它非常优雅和简单(我可能有偏见:)。

不可忽视的一点是,您需要在所有方法或类中注入抽象工厂或具体工厂。

答案 1 :(得分:0)

为什么不使用装饰器?这样,假设你有一些叫做的东西,例如EditQueue,您只需将状态更改推入。您为此创建一个接口,然后提供两个实现,一个是EditQueueImpl,另一个是UndoEnabledEditQueueImpl。第二个是装饰器,里面有一个EditQueueImpl实例,这意味着该类的用户不必知道是否打开了撤销。