设计模式之备忘录模式
备忘录模式:
在不破坏封装性的前提下,铺货一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
备忘录模式结构图:
Originator(原生者): 需要被保存状态以便恢复的那个对象。
Memento(备忘录) : 该对象由Originator创建,主要用来保存Originator的内部状态。
Caretaker(管理者):负责在适当的时间保存/恢复Originator对象的状态。
适用性:
1)必须保存一个对象在某一个时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。
2)如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
优缺点:
1) 保持封装边界 使用备忘录可以避免暴露一些只应由原发器管理却又必须存储在原发器之外的信息。该模式把可能很复杂的Originator内部信息对其他对象屏蔽起来,从而保持了封装边界。
2) 它简化了原发器 在其他的保持封装性的设计中,Originator负责保持客户请求过的内部状态版本。这就把所有存储管理的重任交给了Originator。让客户管理它们请求的状态将会简化Originator,并且使得客户工作结束时无需通知原发器。
3) 使用备忘录可能代价很高 如果原发器在生成备忘录时必须拷贝并存储大量的信息,或者客户非常频繁地创建备忘录和恢复原发器状态,可能会导致非常大的开销。除非封装和恢复Originator状态的开销不大,否则该模式可能并不合适。
4) 维护备忘录的潜在代价 管理器负责删除它所维护的备忘录。然而,管理器不知道备忘录中有多少个状态。因此当存储备忘录时,一个本来很小的管理器,可能会产生大量的存储开销。
例子:
static void Main(string[] args) { //大战Boss前 GameRole lixiaoyao = new GameRole(); lixiaoyao.GetIniState(); lixiaoyao.StateDisplay(); //保存进度 RoleStateCaretaker stateAdmin = new RoleStateCaretaker(); stateAdmin.Memento = lixiaoyao.SaveState(); //大战Boss时,损耗严重 lixiaoyao.Fight(); lixiaoyao.StateDisplay(); //恢复之前状态 lixiaoyao.RecoveryState(stateAdmin.Memento); lixiaoyao.StateDisplay(); Console.Read(); } class GameRole { //生命力 private int vit; public int Vitality { get { return vit; } set { vit = value; } } //攻击力 private int atk; public int Attack { get { return atk; } set { atk = value; } } //防御力 private int def; public int Defense { get { return def; } set { def = value; } } //状态显示 public void StateDisplay() { Console.WriteLine("角色当前状态:"); Console.WriteLine("体力:{0}", this.vit); Console.WriteLine("攻击力:{0}", this.atk); Console.WriteLine("防御力:{0}", this.def); Console.WriteLine(""); } //获得初始状态 public void GetIniState() { this.vit = 100; this.atk = 100; this.def = 100; } //战斗 public void Fight() { this.vit = 0; this.atk = 0; this.def = 0; } //保存角色状态 public RoleStateMemento SaveState() { return (new RoleStateMemento(vit, atk, def)); } //回复角色状态 public void RecoveryState(RoleStateMemento memento) { this.vit = memento.Vitality; this.atk = memento.Attack; this.def = memento.Defense; } } //角色状态存储类 class RoleStateMemento { private int vit; private int atk; private int def; public RoleStateMemento (int vit,int atk,int def) { this.vit = vit; this.atk = atk; this.def = def; } //生命力 public int Vitality { get { return vit; } set { vit = value; } } //攻击力 public int Attack { get { return atk; } set { atk = value; } } //防御力 public int Defense { get { return def; } set { def = value; } } } //角色状态管理类 class RoleStateCaretaker { private RoleStateMemento memento; public RoleStateMemento Memento { get { return memento; } set { memento = value; } } }
备忘录模式与事务回滚
这个例子应该说对于男生比较熟悉,在打CF时,如果没血了,我们会重新开始游戏,又恢复了有血的状态,也可以通过加血,来恢复到原来的攻击力、防御力,备忘录模式的学习让我想起了之前学习过的回滚事件,这两者有一个共同点就是可以通过存储恢复到之前的某一时刻。而备忘录模式 是只要你在代码中使用了此模式,在你需要备份时,就可以备份,不存在处理过程是否出错。
而事务回滚是这样定义的,一组业务整体处理的行为叫一个事务。这一组的业务都能成功处理,我们就可以把这个事务提交来保存你已做的行为结果。但如果一组中有任何的差错出现的话,我们就认为这事务不成功,需要回滚来撤消之前的操作。意思是说只有在事务出现差错时才会使用事务回滚,而如果正常情况下,事务会正常运行下去,不会返回到某一时刻的。
最后更新:2017-04-03 12:55:07