设计模式(十九)—— 备忘录模式

模式简介


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

很多时候我们要记录一个对象的内部状态,为了允许用户撤销不确定的操作或从错误中恢复过来。同时,为了不违反封装的原则,而不能暴露其内部状态和实现。想象一下日常生活中我们经常会遇到重置密码的问题,假设账号密码在初始化后,保留一份备忘录以便今后重置时使用,同样的,我们不能将密码暴露给其它对象。这时,可以使用备忘录模式解决这个问题。

结构分析


UML类图

角色说明

  • Memento

备忘录。存储原发器对象的内部状态,防止原发器以外的对象访问备忘录。

  • Originator

原发器。提供一个方法创建备忘录,用以记录当前时刻它的内部状态,并提供一个使用备忘录恢复内部状态的方法。

  • Caretaker

负责人。负责保存备忘录,不能对备忘录的内容进行操作或检查。

工作原理

管理器向原发器请求一个备忘录,保留一段时间,将其送回原发器。

结构代码

//备忘录
public class Memento
{
private string _state;
public Memento(string state)
{
_state = state;
}

public string GetState()
{
return _state;
}
}

//原发器
public class Originator
{
public string State { get; set; }
public Memento CreateMemento()
{
return new Memento(State);
}
public void SetMemento(Memento memento)
{
Console.WriteLine("Restoring state...");
State = memento.GetState();
}
}

//负责人
public class Caretaker
{
public Memento Memento { get; set; }
}

//客户端调用
class Program
{
static void Main(string[] args)
{
Originator originator = new Originator();
originator.State = "Off";
Caretaker caretaker = new Caretaker();
caretaker.Memento = originator.CreateMemento();
originator.State = "On";
originator.SetMemento(caretaker.Memento);
Console.WriteLine(originator.State);
Console.ReadLine();
}
}

程序输出:

示例分析


本节通过一个重置密码的示例来讲述备忘录模式,首先声明备忘录Memento。

public class Memento
{
public string UserName { get; private set; }
public string Password { get; private set; }
public Memento(string userName,string password)
{
UserName = userName;
Password = password;
}
}

声明原发器User,包含UserName和Password属性,提供CreateMemento方法创建备忘录,以及SetMemento方法提供重置功能。

public class User
{
public string UserName { get; set; }
public string Password { get; set; }
public User(string username,string password)
{
this.UserName = username;
this.Password = password;
}
public Memento CreateMemento()
{
return new Memento(UserName, Password);
}

public void SetMemento(Memento memento)
{
this.UserName = memento.UserName;
this.Password = memento.Password;
}
}

public class UserMemory
{
public Memento Memento { get; set; }
}

客户端调用,创建jack账号并创建备忘录,随后修改了两次密码,最后使用备忘录进行重置。

class Program
{
static void Main(string[] args)
{
User jack = new User("jack", "12345");
UserMemory memory = new UserMemory();
memory.Memento = jack.CreateMemento();
jack.Password = "23456";
jack.Password = "qwert";
jack.SetMemento(memory.Memento);
Console.WriteLine(jack.Password);
Console.ReadLine();
}
}

使用场景


  • 必须保存某个对象在某一时刻的状态,以便以后需要时恢复到该状态。

  • 不希望暴露对象的实现细节以至破坏对象的封装性。

posted @ 2018-07-11 14:36  Answer.Geng  阅读(485)  评论(0)    收藏  举报