我对如何实施纪念品感到非常困惑。
我了解 Memento 有状态。 Memento模式用于存储不同的(之前的)状态,以便可以将对象恢复为之前的状态,
嗯,假设我有多个对象,每个都有10个属性,其中5个属性在每个对象的整个生命周期内保持不变,但是5个哪个改变了。所以我需要为每个对象保存以前的状态并返回它们。
问题:
如何将 Memento Pattern 应用于这些对象?
到目前为止我的想法:
所以 Memento Pattern 有3个类, Memento ,您可以创建多个类,每个州一个。 看守,它存储对象的所有先前状态AKA Mementos 。然后是创建 Mementos 的 Originator ,并从 Memento 获取状态。
这意味着每个对象实例都需要它自己的看守实例(它以前的状态列表),这个看守会将 Mementos 与此对象的5个属性(以及当前状态或仅前面的状态?)的先前状态一起使用,但是看护人的所有对象都可以使用相同的 Originator实例因为 Originator 可用于在任何看守中创建新的纪念品。
这是如何实施的,还是我误解了?
它看起来像这样:
创始人和纪念品课
public class Memento {
private Object1Attributes state;
public Memento(Object1Attributes state){
this.state = state;
}
public Object1Attributes getState(){
return state;
}
}
static class Originator {
private Object1Attributes state;
public Memento saveStateToMemento(){
return new Memento(state);
}
public void getStateFromMemento(Memento Memento){
state = Memento.getState();
}
public void setState(Object1Attributes state){
this.state = state;
}
public Object1Attributes getState(){
return state;
}
}
其他对象
public class Object1Attributes{
string attribute1;
int attribute2;
someObject attribute3;
someObject attribute4;
someObject attribute5;
}
public class Object1 {
CareTaker careTaker = new CareTaker();
Object1Attributes;
string attribute6;
int attribute7;
someObject attribute8;
someObject attribute9;
someObject attribute10;
public void returnToPreviousState(){
if(caretaker.Length()>0){
Object1Attributes = originator.getStateFromMemento(careTaker.get(caretaker.Length()-1));
caretaker.remove(caretaker.Length()-1);
}
}
public void newState(ObjectAttributes OA){
originator.setState(OA);
this.ObjectAttributes = OA;
this.caretaker.add(originator.saveStateToMemento());
}
}
另一个选择
将使Memento类和Originator类保持5个属性,而不是将5个属性封装在另一个类中。像这样:
public class Originator {
string attribute1;
int attribute2;
someObject attribute3;
someObject attribute4;
someObject attribute5;
public Memento saveStateToMemento(){
return new Memento(attribute1, attribute2, attribute3, attribute4, attribute5);
}
public void setAttribute1(string state){
this.attribute1 = state;
}
public void setAttribute2(int state){
this.attribute2 = state;
}
}
这样每个Object1实例都会拥有自己的Originator实例而不是Object1Attributes,而这个Originator将包含object1实例中属性的当前状态;我不知道实现模式的正确方法是哪种方式。
所有在线示例都使用纪念品来存储“状态”,这只是一个字符串,它们都不涉及创建多个可能具有多个状态的对象,所以这就是我不太确定的原因。
答案 0 :(得分:0)
实施Memento模式时常见的一个缺陷是暴露了Originator的内部状态。这打破了一个称为封装的基本OO概念。
Memento有一个捕获Originator状态的州。这可以是外部类型。您还可以在Memento本身中声明所需的属性。稍后您可以使用Mediator的状态将Originator恢复为该状态。
class Memento {
var state: State
}
Originator应该有两个与Memento相关的方法:
class Originator {
func createMemento() -> Memento {
let currentState = State(...)
return Memento(state: currentState)
}
func apply(memento: Memento) {
let restoreState = memento.state
//...set the properties you want to restore from the memento state
}
}
最后,看守:
final class Caretaker {
private lazy var mementos = [String: Memento]()
func saveState(originator: Originator, identifier: String) {
let snapshot: GameWorldMemento = originator.createMemento()
snapshots[identifier] = snapshot
}
func restoreState(originator: Originator, identifier: String) {
if let snapshot = snapshots[identifier] {
originator.apply(memento: snapshot)
}
}
}
这是如何使用它:
let caretaker = CareTaker()
let originator = Originator()
// Save initial state
caretaker.saveState(originator: originator, identifier: "save0")
// modify the originator
// ...
// reset the originator to its original state
caretaker.restoreState(originator: originator, identifier: "save0")
这只是一个简化的例子来说明这个概念。
通常,我首先要定义三种协议。 由于混凝土"发起人"通常已经存在类型,我添加了类型扩展以使其采用Originator协议。这样我就不必修改其代码。实际上,这样我就可以在不修改原始代码的情况下增强类型。
希望这有帮助。