理解设计模式(十八)——备忘录模式

备忘录模式

提出问题

在命令模式中,我们提到了命令模式可以实现撤销。但是命令模式的撤销只能撤销一步,它是通过做上一次操作的反操作来实现的。我们有没有什么办法能够实现撤销无限步?

解决问题

要想撤销无限步,那肯定要把每一步的状态都保存下来,(可以用一个栈来保存)。然后要撤销的时候,只要取出栈顶元素,将状态恢复即可。

思路非常简单,主要是如何保证代码结构的稳定性。我们可以加入一个Memento类,用来保存对象的历史状态。

下面直接上代码:

// 备忘录对象
class Memento {
constructor(state) {
this.state = state;
}

getState() {
return this.state;
}
}

// 这里可以是任何需要撤销的对象
// 我们把它叫做原发器,因为他是状态的来源
class Originator {
constructor(state) {
this.state = state;
}

// 保存
createMemento() {
return new Memento(state);
}

restoreMemento(memento) {
this.state = memento.getState();
}
}

// 用于保存历史状态以及恢复历史状态,实际上可以和Originator合并
class CareTaker {
constructor(originator) {
this.originator = originator;
this.mementoes = [];
}

addMemento(memento) {
this.mementoes.push(memento);
}

getMemento() {
return this.mementoes.pop();
}

do(state) {
addMemento(state);
this.originator.state = state;
}

undo() {
this.originator.restoreMemento(getMemento());
}
}

let originator = new Originator(1);
let caretaker = new CateTaker(originator);

caretaker.do(2);
caretaker.do(3);

caretaker.undo();
caretaker.undo();

总结

这里只实现了undo,如果还要实现redo怎么办呢?再加个redo栈。其实也很简单的,这里就不再说了。

Author: LeoB_O
Link: https://leob-o.github.io/2019/06/15/MementoPattern/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.