设计模式学习笔记——备忘录(Memento)模式
2017-04-13 10:44
471 查看
设计模式学习笔记——备忘录(Memento)模式
@(设计模式)[设计模式, 备忘录模式, memento]设计模式学习笔记备忘录Memento模式
基本介绍
备忘录案例
类图
实现代码
Memento类
Gamer类
测试类
运行结果
备忘录模式中的角色
Originator生成者
Memento纪念品
Caretaker负责人
类图
基本介绍
备忘录模式提供的基本功能是:保存对象状态信息(快照)、撤销、重做和历史记录。备忘录模式一般会提供两种接口:宽接口和窄接口。通过宽接口可以获取整个对象状态,会暴露备忘录对象的内部信息。通过窄接口,只能访问有限的,开发者限制了的信息,可以有效的防止信息泄露。
备忘录案例
类图
实现代码
Memento类
package com.pc.memento.example; import java.util.ArrayList; import java.util.List; /** * 备忘录类 * Created by Switch on 2017/3/31. */ public class Memento { /** * 所持金钱 */ private int money; /** * 获得的水果 */ private List<String> fruits; /** * 获取当前所持金钱 * * @return 所持金钱 */ public int getMoney() { return money; } /** * 构造方法,初始化所持钱数 * * @param money 初始化钱数 */ Memento(int money) { this.money = money; this.fruits = new ArrayList<>(); } /** * 添加水果 * * @param fruit 水果 */ void addFruit(String fruit) { fruits.add(fruit); } /** * 添加当前所持的所有水果 * * @return 水果列表 */ List<String> getFruits() { return fruits; } }
Gamer类
package com.pc.memento.example; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; /** * 游戏者类 * Created by Switch on 2017/3/31. */ public class Gamer { /** * 所持金钱 */ private int money; /** * 获得的水果 */ private List<String> fruits = new ArrayList<>(); /** * 随机数生成器 */ private Random random = new Random(); /** * 表示水果种类的数组 */ private static String[] fruitsname = {"苹果", "葡萄", "香蕉", "橘子"}; /** * 构造方法,初始化金钱数 * * @param money 金钱数 */ public Gamer(int money) { this.money = money; } /** * 获取当前所持金钱数 * * @return 金钱数 */ public int getMoney() { return money; } /** * 投掷骰子进行游戏 */ public void bet() { // 获取骰子数值 int dice = random.nextInt(6) + 1; if (dice == 1) { this.money += 100; System.out.println("所持金钱增加了。"); } else if (dice == 2) { this.money /= 2; System.out.println("所持金钱减半了。"); } else if (dice == 6) { String f = this.getFruit(); System.out.println("获得了水果(" + f + ")。"); this.fruits.add(f); } else { System.out.println("什么都没有发生。"); } } /** * 创建备忘录 * * @return 备忘录对象 */ public Memento createMemento() { Memento m = new Memento(money); Iterator<String> it = fruits.iterator(); while (it.hasNext()) { String fruit = it.next(); if (fruit.startsWith("好吃的")) { m.addFruit(fruit); } } return m; } /** * 撤销到指定备忘 * * @param memento 备忘录对象 */ public void restoreMemento(Memento memento) { this.money = memento.getMoney(); this.fruits = memento.getFruits(); } /** * 获得一个水果 * * @return 水果 */ private String getFruit() { String prefix = ""; if (random.nextBoolean()) { prefix = "好吃的"; } return prefix + fruitsname[random.nextInt(fruitsname.length)]; } @Override public String toString() { return "Gamer{ money=" + money + ", fruits=" + fruits + '}'; } }
测试类
package com.pc.memento.example.test; import com.pc.memento.example.Gamer; import com.pc.memento.example.Memento; import org.junit.Test; /** * Memento Tester. * * @author Switch * @version 1.0 */ public class MementoTest { /** * 测试备忘录模式 */ @Test public void testMemento() { Gamer gamer = new Gamer(100); Memento memento = gamer.createMemento(); for (int i = 0; i < 20; i++) { System.out.println("==== " + i); System.out.println("当前状态:" + gamer); // 投掷骰子 gamer.bet(); System.out.println("所持金钱为" + gamer.getMoney() + "元。"); // 如何处理memento if (gamer.getMoney() > memento.getMoney()) { System.out.println(" (所持金钱增加了许多,因此保存游戏当前的状态)"); memento = gamer.createMemento(); } else if (gamer.getMoney() < memento.getMoney() / 2) { System.out.println(" (所持金钱减少了许多,因此将游戏恢复至以前的状态)"); gamer.restoreMemento(memento); } // 等待一段时间 try { Thread.sleep(100); } catch (InterruptedException e) { } System.out.println(""); } } }
运行结果
==== 0 当前状态:Gamer{ money=100, fruits=[]} 什么都没有发生。 所持金钱为100元。 ==== 1 当前状态:Gamer{ money=100, fruits=[]} 所持金钱减半了。 所持金钱为50元。 ==== 2 当前状态:Gamer{ money=50, fruits=[]} 所持金钱减半了。 所持金钱为25元。 (所持金钱减少了许多,因此将游戏恢复至以前的状态) ==== 3 当前状态:Gamer{ money=100, fruits=[]} 获得了水果(好吃的葡萄)。 所持金钱为100元。 ==== 4 当前状态:Gamer{ money=100, fruits=[好吃的葡萄]} 所持金钱增加了。 所持金钱为200元。 (所持金钱增加了许多,因此保存游戏当前的状态) ==== 5 当前状态:Gamer{ money=200, fruits=[好吃的葡萄]} 所持金钱减半了。 所持金钱为100元。 ==== 6 当前状态:Gamer{ money=100, fruits=[好吃的葡萄]} 获得了水果(葡萄)。 所持金钱为100元。 ==== 7 当前状态:Gamer{ money=100, fruits=[好吃的葡萄, 葡萄]} 所持金钱增加了。 所持金钱为200元。 ==== 8 当前状态:Gamer{ money=200, fruits=[好吃的葡萄, 葡萄]} 所持金钱减半了。 所持金钱为100元。 ==== 9 当前状态:Gamer{ money=100, fruits=[好吃的葡萄, 葡萄]} 所持金钱增加了。 所持金钱为200元。 ==== 10 当前状态:Gamer{ money=200, fruits=[好吃的葡萄, 葡萄]} 什么都没有发生。 所持金钱为200元。 ==== 11 当前状态:Gamer{ money=200, fruits=[好吃的葡萄, 葡萄]} 所持金钱增加了。 所持金钱为300元。 (所持金钱增加了许多,因此保存游戏当前的状态) ==== 12 当前状态:Gamer{ money=300, fruits=[好吃的葡萄, 葡萄]} 所持金钱增加了。 所持金钱为400元。 (所持金钱增加了许多,因此保存游戏当前的状态) ==== 13 当前状态:Gamer{ money=400, fruits=[好吃的葡萄, 葡萄]} 所持金钱减半了。 所持金钱为200元。 ==== 14 当前状态:Gamer{ money=200, fruits=[好吃的葡萄, 葡萄]} 获得了水果(葡萄)。 所持金钱为200元。 ==== 15 当前状态:Gamer{ money=200, fruits=[好吃的葡萄, 葡萄, 葡萄]} 获得了水果(好吃的橘子)。 所持金钱为200元。 ==== 16 当前状态:Gamer{ money=200, fruits=[好吃的葡萄, 葡萄, 葡萄, 好吃的橘子]} 什么都没有发生。 所持金钱为200元。 ==== 17 当前状态:Gamer{ money=200, fruits=[好吃的葡萄, 葡萄, 葡萄, 好吃的橘子]} 所持金钱增加了。 所持金钱为300元。 ==== 18 当前状态:Gamer{ money=300, fruits=[好吃的葡萄, 葡萄, 葡萄, 好吃的橘子]} 所持金钱减半了。 所持金钱为150元。 (所持金钱减少了许多,因此将游戏恢复至以前的状态) ==== 19 当前状态:Gamer{ money=400, fruits=[好吃的葡萄]} 什么都没有发生。 所持金钱为400元。
备忘录模式中的角色
Originator(生成者)
Originator角色会在保存自己的最新状态时生成
Memento角色。当把以前保存的
Memento角色传递给
Originator角色时,它会将自己恢复至生成该
Memento角色时的状态。在案例中,由
Gamer类扮演此角色。
Memento(纪念品)
Memento角色会将
Originator角色的内部信息整合在一起。在
Memento角色中虽然保存了
Originator角色的信息,但它不会向外部公开这些信息。
Memento角色有以下两种接口(
API)。
wide interface——宽接口(
API)
Memento角色提供的“宽接口(
API)”是指所有用于获取恢复对象状态信息的方法的集合。由于宽接口(
API)会暴露所有
Memento角色的内部信息,因此能够使用宽接口(
API)的只有
Originator角色。
narrow interface——窄接口(
API)
Memento角色为外部的
Caretaker角色提供了“窄接口(
API)” 。可以通过窄接口(
API)获取的
Memento角色的内部信息、非常有限,因此可以有效地防止信息泄露。
通过对外提供以上两种接口(
API),可以有效地防止对象的封装性被破坏。
在案例中,由
Memento类扮演此角色。
Originator角色和
Memento角色之间有着非常紧密的联系。
Caretaker(负责人)
当Caretaker角色想要保存当前的
Originator角色的状态时,会通知
Originator角色。
Originator角色在接收到通知后会生成
Memento角色的实例并将其返回给
Caretaker角色。由于以后可能会用
Memento实例来将
Originator恢复至原来的状态,因此
Caretaker角色会一直保存
Memento实例。在案例中,由测试类扮演此角色。
不过,
Caretaker角色只能使用
Memento角色两种接口(
API)中的窄接口(
API),也就是说它无法访问
Memento角色内部的所有信息。它只是将
Originator角色生成的
Memento角色当作一个黑盒子保存起来。
虽然
Originator角色和
Memento角色之间是强关联关系,但
Caretaker角色和
Memento角色之间是弱关联关系。
Memento角色对
Caretaker角色隐藏了自身的内部信息。
类图
GitHub:DesignPatternStudy
——————参考《图解设计模式》
相关文章推荐
- 设计模式之Memento(备忘录)
- 设计模式笔记--行为型模式之六--Memento 备忘录
- Memento(备忘录)——对象行为模式
- 《模式——工程化实现及扩展》(设计模式C# 版)《备忘录模式 Memento》——“自我检验"
- 行为型模式:Memento 备忘录模式
- 备忘录(Memento)模式
- 设计模式学习笔记(二十)——Memento备忘录
- 15 Memento 备忘录模式
- 设计模式----Memento(备忘录)模式
- 设计模式学习-Memento(备忘录)
- 设计模式学习笔记(十七)—Memento备忘录模式
- 存档读档的Memento——备忘录模式
- Memento备忘录模式
- Memento(备忘录)——对象行为模式
- 设计模式----Memento(备忘录)
- Java设计模式-----Memento备忘录模式
- 设计模式—Memento备忘录模式
- 设计模式--Memento 备忘录模式
- 《GOF设计模式》—备忘录(MEMENTO)—Delphi源码示例:一个反映备忘录模式的迭代接口
- 设计模式学习-Memento(备忘录)