备忘录模式

目录

一、什么是备忘录模式?

二、备忘录模式有什么优点吗?

2.1、封装状态:

2.2、实现撤销和恢复功能:

2.3、简化原始对象:

2.4、对用户友好的接口:

2.5、支持多次撤销:

2.6、实现历史记录:

2.7、灵活性和可扩展性:

2.8、解耦状态保存:

三、有什么缺点吗?

四、什么场合使用备忘录模式?

五、代码展示

5.1、发起人(Originator)类

5.2、备忘录(Memento)类

5.3、管理类(Caretaker)类

5.4、客户端


一、什么是备忘录模式?

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。

比如像我们平常使用的Ctrl+Z撤销操作、浏览器里面的回退操作、还有数据库的事务回滚、手机相册删除的照片可以恢复,这些都是让你吃“后悔药”的行为。体现了备忘录模式。

备忘录模式_第1张图片

Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的那些内部状态。

Memento(备忘录):负责存储Originator对象的内部状态。

Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。

二、备忘录模式有什么优点吗?

备忘录模式在一些需要实现撤销、恢复或历史记录功能的场景中非常有用。以下是备忘录模式的一些优点:

2.1、封装状态:

备忘录模式通过将对象的状态封装在备忘录对象中,避免了在原对象中暴露状态的细节。这有助于保持对象的封装性和数据隐私。

2.2、实现撤销和恢复功能:

备忘录模式使得对象可以在不同的时间点保存其状态,并在需要时恢复到之前的某个状态。这为实现撤销和恢复功能提供了一种有效的机制。

2.3、简化原始对象:

通过将状态保存在备忘录中,原始对象不再需要维护多个历史状态,从而减轻了原始对象的负担,使其更加专注于核心业务逻辑。

2.4、对用户友好的接口:

备忘录模式将状态保存和恢复的逻辑封装在备忘录对象中,为用户提供了简单和一致的接口,用户无需关心内部实现细节。

2.5、支持多次撤销:

备忘录模式可以保存多个状态快照,使得对象可以在不同的时间点进行多次撤销操作。

2.6、实现历史记录:

备忘录模式可以用于实现对象的历史记录,记录对象的不同状态变化,为审计和分析提供支持。

2.7、灵活性和可扩展性:

备忘录模式允许在不修改原始对象的情况下新增备忘录类型,从而提供了灵活性和可扩展性,适应不同的需求。

2.8、解耦状态保存:

备忘录模式将状态保存和恢复的职责从原始对象中解耦,减少了原始对象的复杂性,使得代码更易于维护和理解。

三、有什么缺点吗?

  1. 资源消耗: 备忘录模式需要在备忘录对象中保存对象的状态,如果对象的状态较大或者状态变化频繁,可能会消耗较多的内存资源。这特别在需要保存多个历史状态时会更为显著。

  2. 效率问题: 在一些情况下,备忘录模式可能会导致性能问题。每次保存状态都需要创建一个备忘录对象,这涉及到对象的拷贝操作,而拷贝操作可能会耗费较多的时间。

  3. 复杂性增加: 备忘录模式引入了备忘录类,使得代码中涉及到更多的类和交互,从而增加了代码的复杂性。尤其是在需要保存多个对象的状态时,代码可能会变得更加繁琐。

  4. 封装破坏: 尽管备忘录模式通过封装对象的状态实现了信息隐蔽,但它也可能破坏了对象的一致性。因为备忘录对象需要访问原始对象的状态,可能会使得原始对象的一些私有属性暴露给外部。

  5. 状态一致性问题: 在某些情况下,备忘录模式可能会引入状态一致性问题。如果备忘录对象不正确地保存了对象的状态,或者在恢复状态时发生了错误,可能导致对象的状态不一致。

  6. 不适合大规模状态变化: 备忘录模式更适用于状态变化频率较低的场景。如果对象的状态变化非常频繁,可能会导致备忘录对象的数量急剧增加,从而增加了管理和维护的难度。

  7. 无法回滚外部资源: 如果对象的状态不仅仅包括内部数据,还包括外部资源的状态(例如数据库连接),备忘录模式可能无法正确地回滚外部资源的状态。

四、什么场合使用备忘录模式?

适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。

如果再某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。

使用备忘录可以把负责的对象内部信息对其他的对象屏蔽起来。

当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。

五、代码展示

场景:游戏的某个场景,一游戏角色有生命力、攻击力、防御力等等数据,在打Boss前和后一定会不一样的,我们允许玩家如果感觉与Boss决斗的效果不理想可以让游戏回复到决斗前。

①、备忘录模式

备忘录模式_第2张图片

5.1、发起人(Originator)类

    class Originator
    {
        private string state;        //成员变量
        public string State          //需要保存的属性
        {
            get { return state; }
            set { state = value; }
        }

        //创建备忘录
        public Memento CreateMemento()
        {
            //讲当前需要保存的信息导入并实例化出一个Memento对象
            return (new Memento(state));
        }

        //恢复备忘录
        public void SetMemento(Memento memento)
        {            
            state = memento.State;    //将Memento导入并将相关数据恢复
        }

        //显示数据
        public void Show()
        {
            Console.WriteLine("State={0}", state);
        }
    }

5.2、备忘录(Memento)类

    class Memento
    {
        private string state;         //成员变量,状态
        public Memento(string state)  //有参构造方法
        {
            this.state = state;
        }

        public string State            //需要保存的数据属性,可以是多个
        {
            get { return state; }       //只能保存数据,防止外界修改
        }
    }

5.3、管理类(Caretaker)类

    class Caretaker
    {
        private Memento memento;
        public Memento Memento         //得到或设置备忘录
        {
            get { return memento; }
            set { memento = value; }
        }
    }

5.4、客户端

Originator o = new Originator();    //实例化一个发起人
o.State = "On";                 //初始状态属性为“On”
o.Show();                       //显示当前状态

Caretaker c = new Caretaker();      //创建一个管理者
//发起人创建一个备忘录,将创建的备忘录复制给管理者的属性
c.Memento = o.CreateMemento();      
            

o.State = "Off";        //状态属性为“Off”
o.Show();               //显示当前状态

o.SetMemento(c.Memento);    //管理者调用保存的数据赋值给发起人并恢复备忘录
o.Show();                   //显示当前状态

Console.ReadKey();

image.png

 

你可能感兴趣的:(设计模式,备忘录模式)