备忘录模式1_大话设计模式学习笔记18

   日期:2020-05-11     浏览:93    评论:0    
核心提示:现编写一个代码,模拟游戏里的某个场景:游戏角色有生命力、攻击力、防御力等属性,他在打Boss前进行存档(满状态),然后去打Boss(被打成瓜皮)。体验完被虐的感受后,再读取之前满状态时的档案,又开始愉快地玩耍了。> ps:主要是体现存档、读档如何进行,而不是什么打斗场景。这是设计模式笔记!!!设计模式

大鸟给小菜的问题:

现编写一个代码,模拟游戏里的某个场景:游戏角色有生命力、攻击力、防御力等属性,他在打Boss前进行存档(满状态),然后去打Boss(被打成瓜皮)。体验完被虐的感受后,再读取之前满状态时的档案,又开始愉快地玩耍了。
ps:主要是体现存档、读档如何进行,而不是什么打斗场景。这是设计模式笔记!!!

1、小菜经过短暂的思考,快速地写出来他的答案:

  • 直接来一个游戏角色类,生命力、攻击力、防御力用类的成员变量体现;
  • 再编写几个方法:1、状态显示;2、角色属性初始化;3、战斗后角色属性变化
  • 至于存档与读档的操作通过客户端来表示。

(1)游戏角色类

public class GameRole {
	private int vit;	// 生命力
	private int atk;	// 攻击力
	private int def;	// 防御力
	
	public void Vitality(int vit) {	// 得到生命力的值
		this.vit = vit;
	}
	public int Vitality() {	// 修改生命力的值
		return vit;
	}
	public void Attack(int atk) {	// 得到攻击力的值
		this.atk = atk;
	}
	public int Attack() {	// 修改攻击力的值
		return atk;
	}
	public void Defense(int def) {	// 得到防御力的值
		this.def = def;
	}
	public int Defense() {	// 修改防御力的值
		return def;
	}
	
	// 显示当前状态
	public void StateDisplay() {
		System.out.println("角色当前状态:");
		System.out.println("体力:" + this.vit);
		System.out.println("攻击力:" + this.atk);
		System.out.println("防御力:" + this.def);
		System.out.println("……");
	}
	public void GetInitState() {	// 状态初始化
		this.vit = 100;
		this.atk = 100;
		this.def = 100;
	}
	public void Fight() {	// 战斗后属性改变
		this.vit = 0;
		this.atk = 0;
		this.def = 0;
	}
}

(2)客户端代码

public class Memento1Demo {

	public static void main(String[] args) {
		// 大战Boss前
		GameRole lixiaoyao = new GameRole();
		lixiaoyao.GetInitState();	// 满状态
		lixiaoyao.StateDisplay();	// 显示当前状态
		
		// 进程存档
		GameRole backup = new GameRole();	
		backup.Vitality(lixiaoyao.Vitality());
		backup.Attack(lixiaoyao.Attack());
		backup.Defense(lixiaoyao.Defense());
		
		lixiaoyao.Fight();	// 大战
		lixiaoyao.StateDisplay();	// 显示大战后的状态
		
		// 读档
		lixiaoyao.Vitality(backup.Vitality());
		lixiaoyao.Attack(backup.Attack());
		lixiaoyao.Defense(backup.Defense());
		
		lixiaoyao.StateDisplay();
		
	}

}

(3)输出结果

角色当前状态:
体力:100
攻击力:100
防御力:100
……
角色当前状态:
体力:0
攻击力:0
防御力:0
……
角色当前状态:
体力:100
攻击力:100
防御力:100
……

代码分析:

从功能实现来说,提出的要求都完成了。存档了,读档了,没别的遗漏。
但是从代码内容的结构来说,这编写极其糟糕!

  • 首先,对于存档和读档来说,确实是从客户端发出这个操作,但请主要,这只能是发出请求,而不是执行这个请求。真正是在内部进行该操作,而上述代码就是犯了这个错!——简单来说,就是一点也不封闭!!!
 
 // 进程存档 
		GameRole backup = new GameRole();	
 		backup.Vitality(lixiaoyao.Vitality());
 		backup.Attack(lixiaoyao.Attack());
 		backup.Defense(lixiaoyao.Defense());
 
// 读档
  		lixiaoyao.Vitality(backup.Vitality());
 		lixiaoyao.Attack(backup.Attack());
 		lixiaoyao.Defense(backup.Defense());
  • 其次,一点也不开发放!!!
    例如,现在还有一个经验值(experience)的属性参数要加进去,安排小菜给的这份代码来说,那是不是需要加上:
backup.Experience(lixiaoyao.Experience());

lixiaoyao.Experience(backup.Experience());

修改方向:

客户端的调用在这份代码里的比重太大了,这就导致了一有什么改动,客户端也要进行修改,但客户端本来就不是需要经常修改的地方。套用一下课本的原话:显然,我们希望的是把这些“游戏角色”的存取状态封装起来,而且最好是封装在外部的类当中。
还有一点需要明白,客户端是发出操作请求的地方,不是进行具体操作内容的地方。

二、经过对“备忘录模式”的学习理解,小菜给出了他修改后的代码:


(1)、还是先“游戏角色类”说起

老版本的那些内容都保留了下来:几个属性参数(生命力、攻击力、防御力)还有几个函数(初始化角色、显示角色状态、角色大战后参数改变);当然,那些get、set方法这里就省略了。
在这些基础上,区别是把在客户端里进行的存档、读档操作封装到类中,各自对应一个方法。

  • 如何去表示档案?:
    就是将这些参数数据再包装起来,又存储到一个“备忘录”类中。
public class GameRole {
	private int vit;	// 生命力
	private int atk;	// 攻击力
	private int def;	// 防御力
	
	public RoleStateMemento SaveState() {	// 创建档案
		return new RoleStateMemento(vit, atk, def);
	}
	
	public void RecoveryState(RoleStateMemento memento) {	// 读档
		this.vit = memento.Vitality();
		this.atk = memento.Attack();
		this.def = memento.Defense();
	}
	
	public void StateDisplay() {	// 角色当前状态
		System.out.println("角色当前状态:");
		System.out.println("体力:" + this.vit);
		System.out.println("攻击力:" + this.atk);
		System.out.println("防御力:" + this.def);
		System.out.println("……");
	}
	public void GetInitState() {	// 初始化
		this.vit = 100;
		this.atk = 100;
		this.def = 100;
	}
	public void Fight() {	// 战斗
		this.vit = 0;
		this.atk = 0;
		this.def = 0;
	}
}

(2)、备忘录类——角色状态存储箱类

发起人类(游戏角色类)里有啥成员变量,备忘录类(角色状态存储箱类)就有啥成员变量。

public class RoleStateMemento {	// 角色状态存储箱类
	private int vit;	// 生命力
	private int atk;	// 攻击力
	private int def;	// 防御力

	public RoleStateMemento(int vit, int atk, int def) {
		this.vit = vit;
		this.atk = atk;
		this.def = def;
	}
	
	// 修改、获得各个状态属性
	public void Vitality(int vit) {
		this.vit = vit;
	}
	public int Vitality() {
		return vit;
	}
	public void Attack(int atk) {
		this.atk = atk;
	}
	public int Attack() {
		return atk;
	}
	public void Defense(int def) {
		this.def = def;
	}
	public int Defense() {
		return def;
	}
}

(3)管理者类——角色状态管理者类

  • 认真看下备忘录类和备忘录的管理者类,有什么细节发现?
    管理者类虽然是管理者,当只能是选择备忘录,而不是修改备忘录,准确是无法修改备忘录里的属性参数。
    就是说只有备忘录类自己才能操作自身的那些参数(生命力、攻击力、防御力),而管理者类它负责的只能是决定存取哪个备忘录类。
public class RoleStateCaretaker {	// 角色状态管理者类
	private RoleStateMemento memento;	// 档案

	public RoleStateMemento getMemento() {
		return memento;
	}
	public void setMemento(RoleStateMemento roleStateMemento) {
		this.memento = roleStateMemento;
	}	
	
}

(4)、客户端代码

public class Memeto3Demo {

	public static void main(String[] args) {
		// 大战Boss类
		GameRole lixiaoyao = new GameRole();	// 创建角色
		lixiaoyao.GetInitState();	// 初始化
		lixiaoyao.StateDisplay();	// 当前状态展示
		
		// 保存进度
		RoleStateCaretaker stateAdmin = new RoleStateCaretaker();
		stateAdmin.setMemento(lixiaoyao.SaveState());
		
		
		lixiaoyao.Fight();	// 大战
		lixiaoyao.StateDisplay();	// 当前状态展示
		
		lixiaoyao.RecoveryState(stateAdmin.getMemento());	// 取档
		lixiaoyao.StateDisplay();	// 当前状态展示
	}

}

(5)、输出结果

角色当前状态:
体力:100
攻击力:100
防御力:100
……
角色当前状态:
体力:0
攻击力:0
防御力:0
……
角色当前状态:
体力:100
攻击力:100
防御力:100
……

最后的话:

备忘录模式的结构就三部分:

  • 1、发起人(Originator)类:也可以理解成是你游戏里的角色,里面有很多参数(数据),有两个特殊方法:存档方法、读档方法。
  • 2、备忘录(Memento)类:里面的成员变量就是发起人类里需要存储的内容。
  • 3、管理者(Caretaker)类:存储备忘录类,无法操作备忘录类里的数据。

感谢读者能坚持看到这里的,如果可以的话希望帮忙点个小赞,虽然是学习笔记,但还是在线乞讨!!!真的十分感谢!

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服