了解23种设计模式之备忘录模式

    技术2025-05-24  52

    了解23种设计模式之备忘录模式

    什么是备忘录模式备忘录模式结构,特点代码实现应用实例

    什么是备忘录模式

    简单来说:如果能够回到从前。。。。

    每个人都有犯错的时候,都希望有种后悔药,能弥补自己的过失,让自己重新开始,但现实是残酷的。在计算机应用中,客户同样会常常犯错误,能否提供“后悔药”给他们呢?当然是可以的,而且是有必要的。这个功能由“备忘录模式”来实现。

    有很多软件都实现了这个功能, Word,记事本,Eclipse,idea 在编辑时按 Ctrl+Z 组合键时能撤销当前操作,使文档恢复到之前的状态;还有在 IE 中的后退键、数据库事务管理中的回滚操作、玩游戏时的中间结果存档功能、数据库与操作系统的备份操作、棋类游戏中的悔棋功能等都属于这类。

    备忘录模式(Memento):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。该模式又叫快照模式。

    备忘录模式结构,特点

    优点: 1,提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。 2,实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。 3,简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。

    缺点:资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。

    备忘录角色:

    发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

    结构图如下:

    代码实现

    发起人(Originator)角色: 记录当时时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。

    public class Originator { private String state; /** * 创建一个备忘录,将当前的需要保存的信息导入并实例化出一个Memento对象 * @param * @return */ public Memento CreateMemento() { return new Memento(state); } /** * 恢复备忘录,将Memento对象导入并将相关信息恢复 * @param * @return */ public void setMemento(Memento memento) { this.state = memento.getState(); } public String getState() { return state; } public void setState(String state) { this.state = state; } public void show(){ System.out.println("state = "+ state); } }

    备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。

    public class Memento { private String state; public Memento(String state) { this.state = state; } public String getState() { return state; } public void setState(String state) { this.state = state; } }

    管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改

    public class Caretaker { private Memento memento; /** * 得到备忘录 * @return */ public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } }

    测试结果: 把要保存的细节封装到 Memento 中。哪天要更改保存的细节也不用影响客户端

    public class MainClass { public static void main(String[] args) { //创建一个发起人 Originator or=new Originator(); //创建一个管理者 Caretaker cr=new Caretaker(); //改变对象内部属性,保存状态 or.setState("On"); System.out.println("初始状态:"); or.show(); cr.setMemento(or.CreateMemento()); //修改发起人的属性 or.setState("Off"); System.out.println("新的状态:"); or.show(); //恢复状态,获得对象内部属性 or.setMemento(cr.getMemento()); System.out.println("恢复状态:"); or.show(); } }

    应用实例

    1,需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。 2,需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,Eclipse 等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。

    实现游戏保存

    发起人: 游戏角色 负责

    public class GameRole { //生命力 private int vitality; //攻击力 private int Attackpower; //防御力 private int Defense; /** * 创建一个角色状态 * @return */ public GameRoleStateMemento createMemento(){ return new GameRoleStateMemento(vitality,Attackpower,Defense); } /** * 保存一个角色状态 * @return */ public void setMemento(GameRoleStateMemento memento){ this.vitality = memento.getVitality(); this.Attackpower = memento.getAttackpower(); this.Defense = memento.getDefense(); } public int getVitality() { return vitality; } public void setVitality(int vitality) { this.vitality = vitality; } public int getAttackpower() { return Attackpower; } public void setAttackpower(int attackpower) { Attackpower = attackpower; } public int getDefense() { return Defense; } public void setDefense(int defense) { Defense = defense; } public void show(){ System.out.println("角色生命力:"+this.vitality+ " 角色攻击力:"+this.Attackpower+" 角色防御力:"+this.Defense); } }

    备忘录,游戏角色备忘录

    public class GameRoleStateMemento { //生命力 private int vitality; //攻击力 private int Attackpower; //防御力 private int Defense; public GameRoleStateMemento(int vitality, int attackpower, int defense) { this.vitality = vitality; Attackpower = attackpower; Defense = defense; } public int getVitality() { return vitality; } public void setVitality(int vitality) { this.vitality = vitality; } public int getAttackpower() { return Attackpower; } public void setAttackpower(int attackpower) { Attackpower = attackpower; } public int getDefense() { return Defense; } public void setDefense(int defense) { Defense = defense; } }

    管理者

    public class RoleStateCaretaker { private GameRoleStateMemento Memento; public GameRoleStateMemento getMemento() { return Memento; } public void setMemento(GameRoleStateMemento memento) { Memento = memento; } }

    测试结果:

    public class MainClass { public static void main(String[] args) { GameRole gameRole=new GameRole(); RoleStateCaretaker cr=new RoleStateCaretaker(); gameRole.setVitality(2000); gameRole.setAttackpower(9000); gameRole.setDefense(150); System.out.println("初始状态:"); gameRole.show(); //保存状态 cr.setMemento(gameRole.createMemento()); gameRole.setVitality(500); gameRole.setAttackpower(5000); gameRole.setDefense(100); System.out.println("新的状态:"); gameRole.show(); //恢复状态 gameRole.setMemento(cr.getMemento()); System.out.println("恢复状态:"); gameRole.show(); } }

    Processed: 0.009, SQL: 9