了解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();
    }
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可乐cc呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值