[设计模式] - 备忘录模式

一、备忘录模式简介

1. 什么是中介者模式

备忘录模式(Memento Pattern) 属于行为型设计模式的一种,其定义为:Without violating encapsulation , capture and externalize an objects internal state to that the object can be restored to this state later(在不破坏封装性的前提下,捕获一个对象内部的状态并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原来保存的状态)。简单来说,备忘录模式就是为目标对象创建一个备份并且提供对应的还原方法,为我们的操作提供一颗后悔药。

2. 业务场景

备忘录模式是一种既简单又实用的设计模式,备忘录模式在日常生活中其实是有很多的应用,比如大话西游中至尊宝使用的月光宝盒,抑或是游戏中的Save/Load大法。不知道屏幕前的你是否喜欢打游戏?很多游戏都为我们提供了存档功能,而很多玩家为了达到一个完美的通关效果都会选择采取Save/Load的方式来处理很多游戏中的难点和细节。在这里读取存档和保存存档的方式就是一个典型的备忘录模式。当我们点击Save的时候,我们将此时的游戏状态保存进了磁盘中以用来在我们需要的时候可以通过Load操作读取出之前保存的状态。
在这里插入图片描述
那么我们今天就通过简单的代码来实现一个游戏的Save/Load功能。

二、备忘录模式的实现

1. 设计思路

第一步我们需要制定一个简单的游戏流程:
在这里插入图片描述
第二步我们需要简单的分析下这个流程中存在多少个对象。

  1. 游戏对象(game):负责游戏本身属性和行为的记录
  2. 备份对象(memento):负责记录制定之间点游戏的状态
  3. 备份管理对象(caretaker):负责维护游戏的备份

接下来请看代码实现:

2. 备忘录模式的代码实现

1. 创建游戏对象

public class Game {

	// 生命值
	private Long hp = 1000l;
	// 魔法值
	private Long mp = 500l;
	// 游戏进度
	private Integer level = 1;

	public void gameStart() {
		System.out.println("游戏开始了!");
	}

	public void run() {
		// 游戏进行 减少hp和mp 增加level
		hp -= 300l;
		mp -= 100l;
		level += 1;
		if (hp <= 0) {
			System.out.println("hp低于0,游戏结束!");
		} else {
			getState();
		}
	}

	// 获取此时游戏状态
	public void getState() {
		System.out.println("-----------------------------");
		System.out.println("此时人物Hp为:" + hp);
		System.out.println("此时人物Mp为:" + mp);
		System.out.println("此时游戏进度:" + level);
	}

	public void save(Memento memento) {
		memento.save(this);
	}

	public void load(Memento memento) {
		System.out.println("读取游戏进度");
		Game game = memento.load();
		this.hp = game.hp;
		this.mp = game.mp;
		this.level = game.level;
		getState();
	}

	public Long getHp() {
		return hp;
	}

	public void setHp(Long hp) {
		this.hp = hp;
	}

	public Long getMp() {
		return mp;
	}

	public void setMp(Long mp) {
		this.mp = mp;
	}

	public Integer getLevel() {
		return level;
	}

	public void setLevel(Integer level) {
		this.level = level;
	}

}

2. 创建游戏备份对象

public class Memento {
	private Game game = new Game();

	public void save(Game game) {
		this.game.setHp(game.getHp());
		this.game.setMp(game.getMp());
		this.game.setLevel(game.getLevel());
	}

	public Game load() {
		// TODO Auto-generated method stub
		return game;
	}

}

3. 创建备份管理器

public class Catetaker {

	private Memento memento;

	public void setMemento(Memento memento) {
		this.memento = memento;
	}

	public Memento getMemento() {
		return this.memento;
	}
}

测试代码

public class Client {
	public static void main(String[] args) {
		Game game = new Game();
		Catetaker catetaker = new Catetaker();
		catetaker.setMemento(new Memento());
		game.gameStart();
		game.run();
		game.save(catetaker.getMemento());
		game.run();
		game.load(catetaker.getMemento());
	}

}

测试结果:
在这里插入图片描述
到这里,一个简单的游戏save/load模型就做完了。

3. 备忘录模式的类图设计

在这里插入图片描述

  1. Originator(发起人角色): 记录当前对象状态和行为。
  2. Menento(备忘录角色):负责存储发起者内部状态并提供还原方法。
  3. Caretaker(备忘录管理员):负责备忘录角色的存储和管理。

三、备忘录模式总结

1. 备忘录模式的特点

优点:

  1. 提供给用户一个可恢复状态的机制,常用来搭配命令模式使用。
  2. 实现了信息的封装,用户无需关心信息的细节。

缺点

  1. 消耗资源,如果需要备份的对象过多,会造成额外的资源浪费。

2. 备忘录模式的使用场景

  1. 搭配命令模式提供撤销指令
  2. 需要保存/恢复数据的场景

3. 拓展

(1)原型模式搭配使用备忘录

我们在备份对象的时候可以使用原型模式来达到更快速的复制对象的目的。

(2)多状态备忘录的使用

有些同学会疑问在上面的例子中Caretaker对象并不是必须的,这里要简单说下,其实Caretaker对象主要是用来管理多状态对象的备份的。如果一个对象可以同时创建多个状态不同的备份,这个时候就需要我们通过Caretaker对象进行管理和维护。

四、结语

今天的代理模式讲解就全部结束了,设计模式的相关代码已经在gitee上收录,有需求的小伙伴可以直接拿走:

https://gitee.com/xiaolong-oba/csdn-learning-code.git

有疑问的小伙伴欢迎评论区留言或者私信博主,博主会在第一时间为你解答。
码字不易,感到有收获的小伙伴记得要关注博主一键三连,不要当白嫖怪哦~
博主在这里祝大家可以在新的一年升职加薪,走上人生巅峰!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

晓龙oba

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

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

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

打赏作者

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

抵扣说明:

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

余额充值