首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用memento设计模式保存多个对象的状态?

如何使用memento设计模式保存多个对象的状态?
EN

Stack Overflow用户
提问于 2016-11-24 23:28:30
回答 1查看 2.5K关注 0票数 5

我对备忘录应该如何实现感到非常困惑。

我知道Memento有一个StateMemento模式用于存储不同的(先前的)状态,以便可以将对象还原到以前的状态

假设我有多个对象,每个属性都有10个属性,其中5个属性在每个对象的整个生命周期中保持不变,但其中5个属性会发生变化。因此,对于每个对象,我需要保存它以前的状态并返回到它们。

问题:

如何将Memento模式应用于这些对象?

到目前为止我的想法:

因此,Memento模式有3个类,Memento,您创建了许多类,每个状态都有一个。,它存储AKA 纪念品的所有以前的状态。然后是发起人,它创建Mementos,并从Memento获取状态。

这意味着每个对象实例都需要它自己的看管器实例(它以前状态的列表),并且这个看门人将使用 mementos ,其中包含该对象的5个属性的先前状态(以及当前状态还是仅是以前的状态?),但是所有具有托管器的对象都可以使用相同的原始实例E 249,因为E 150发起人E 251可以用于在任何E 152看护器E 253中创建新的mementos。

这是如何实施的,还是我误解了?

看起来会是这样的:

发起人和Memento类

代码语言:javascript
复制
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;
   }

}

其他物体

代码语言:javascript
复制
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类和发起人类保存这5个属性,而不是将5个属性封装在另一个类中。就像这样:

代码语言:javascript
复制
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实例将保存自己的发起人实例,而不是Object1Attributes,并且这个发起者将包含object1实例中属性的当前状态;我不知道实现模式的正确方式是哪种方式。

所有在线示例都使用mementos存储一个"state“,它只是一个字符串,它们中没有一个涉及创建可以具有多个状态的多个对象,这就是为什么我如此不确定的原因。

EN

回答 1

Stack Overflow用户

发布于 2017-11-09 14:03:33

实现Memento模式时常见的缺陷之一是公开发起人的内部状态。这打破了一个被称为封装的基本的面向对象概念。

Memento有一个捕获发起人状态的状态。这可以是外部类型。您还可以在Memento本身中声明所需的属性。稍后,您可以使用Mediator的状态将发起人还原回该状态。

代码语言:javascript
复制
class Memento {
    var state: State
}

发起人应当有两种与记忆有关的方法:

代码语言:javascript
复制
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
    }
}

最后,看守:

代码语言:javascript
复制
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)
        }
    }
}

这就是如何使用它:

代码语言:javascript
复制
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")

这只是一个简单的例子来说明这个概念。

通常情况下,我会从定义这三个协议开始。由于具体的“发起人”通常已经存在类型,所以我会添加一个类型扩展来使它采用发起人协议。这样我就不用修改它的代码了。实际上,这样我就可以在不修改原始代码的情况下增强类型。

希望这能有所帮助。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40795754

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档