设计模式之备忘录模式

来源:互联网 发布:怎么看自己的淘宝联盟i 编辑:程序博客网 时间:2024/03/29 07:27

前言:

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

一.备忘录模式简介

备忘录模式(Memento Pattern)适用于功能比较复杂,但需要维护和记录的历史类,或者需要保存属性只是众多属性中的一小部分时,用备忘录模式可以将信息还原。

二.备忘录模式的实例讲解

案例:游戏主角在战斗中死亡后复活,可以通过备忘录模式实现。

1.产品设计UML类图

这里写图片描述
(图片加载慢,多刷新几下,耐心等待……)

注:管理者类Caretaker和备忘录类Memento是聚合关系,Caretaker包含Memento,但不是Memento的一部分。

聚合关系:表示一种弱的"拥有"关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。

2.游戏角色类(发起人)

设计分析:创建一个备忘录类(Memento),实现保存游戏角色的状态,并且可以恢复游戏角色的状态。可以根据需求,有选择的决定保存那些状态,这里只保存游戏角色的生命值hp、攻击力atk、防御力def

package com.patttern.originator;import com.patttern.memento.Memento;/** * 创建一个备忘录,储存状态,用于还原 */public class Originator {    // 生命值    private int hp;    // 攻击力    private int atk;    // 防御力    private int def;    // 状态    private String state;    // 角色姓名    private String name;    //显示当前状态    public void showState() {        System.out.println(getName() + "当前状态:生命值:" + getHp() + ",攻击力:" + getAtk() + ",防御力" + getDef());    }    //初始化角色状态    public void getInitState(String name) {        setName(name);        setHp(1000);        setAtk(80);        setDef(50);    }    //被击杀,状态清零    public void killed() {        setHp(0);        setAtk(0);        setDef(0);    }    //创建备忘录对象    public Memento CreateMemento() {        return new Memento();    }    //保存角色状态到备忘录中    public Memento saveState() {        return new Memento(hp, atk, def);    }    //恢复数据    public void recoveryState(Memento memento) {        this.hp = memento.getHp();        this.atk = memento.getAtk();        this.def = memento.getDef();    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getState() {        return state;    }    public void setState(String state) {        this.state = state;    }    public int getHp() {        return hp;    }    public void setHp(int hp) {        this.hp = hp;    }    public int getAtk() {        return atk;    }    public void setAtk(int atk) {        this.atk = atk;    }    public int getDef() {        return def;    }    public void setDef(int def) {        this.def = def;    }}

3.备忘录类

设计分析: 储存游戏角色的状态,并禁止该游戏角色以外的其他对象对备忘录的访问。备忘录有两个接口,一个宽接口对游戏角色(Originator)开放,使游戏角色可以恢复状态数据;另一个窄接口,对管理者(Caretaker)公开,它只能将备忘录传递给其他对象。

ppackage com.patttern.memento;/** * 备忘录:用于保存状态数据 *  */public class Memento {    //生命值    private int hp;    //攻击力    private int atk;    //防御力    private int def;    public Memento() {    }    public Memento(int hp, int atk, int def) {        this.hp = hp;        this.atk = atk;        this.def = def;    }    public int getHp() {        return hp;    }    public void setHp(int hp) {        this.hp = hp;    }    public int getAtk() {        return atk;    }    public void setAtk(int atk) {        this.atk = atk;    }    public int getDef() {        return def;    }    public void setDef(int def) {        this.def = def;    }}

4.管理者类(Caretaker)

设计分析: 维护一个备忘录Memento对象的具体实例,只能管理备忘录,但不能对其内容操作和检查。

为什么不直接在客户端中维护备忘录Memento,而非要在Caretaker中维护呢?这是因为开发中要符合迪米特法则,让客户端和备忘录Memento不直接通信,而在管理者的帮助下完成通信。

迪米特法则:如果两个类不直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类要调用另一个类中某个方法的话,可通过第三者转发这个调用。

代码如下:

package com.patttern.caretaker;import com.patttern.memento.Memento;/** * 管理角色状态 * */public class Caretaker {    //管理备忘录对象    private Memento memento;    public Memento getMemento() {        return memento;    }    public void setMemento(Memento memento) {        this.memento = memento;    }}

5.客户端中使用

模拟英雄盖伦的生命周期,创建人物-备份状态-战斗死亡-复活恢复状态。

package com.patttern.client;import com.patttern.caretaker.Caretaker;import com.patttern.originator.Originator;public class Client {    public static void main(String[] args) {        //初始化        Originator garen = new Originator();        garen.getInitState("盖伦");        garen.showState();        //备份状态        Caretaker caretaker = new Caretaker();        caretaker.setMemento(garen.saveState());        //在战斗中被杀        garen.killed();        garen.showState();        //复活-恢复状态        garen.recoveryState(caretaker.getMemento());        garen.showState();    }}

6.运行结果展示

盖伦当前状态:生命值:1000,攻击力:80,防御力50盖伦当前状态:生命值:0,攻击力:0,防御力0盖伦当前状态:生命值:1000,攻击力:80,防御力50

7.源码下载

本文示例代码下载地址:点击下载

三.总结:

备忘录模式适合应用于复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性的一部分时,Originator类可以根据备忘录中的信息还原到以前状态。

1.备忘录模式的优点

  • 方便用户恢复到某个历史状态,如撤销功能。
  • 实现了对状态信息的封装,用户不需要关心保存细节。

2.备忘录模式的缺点

  • 若果状态成员变量过多,每次保存都会消耗很多内存资源。
原创粉丝点击