23种设计模式——备忘录模式

备忘录模式是一种设计模式,用于在不破坏封装性的前提下保存对象的内部状态并恢复。本文通过游戏进度存档和象棋悔棋的例子详细解释了备忘录模式的实现,包括Originator、Memento和CareTaker三个角色的职责,以及模式的优缺点。适用场景主要是在需要保存和恢复对象状态时,例如在游戏保存进度或实现象棋悔棋功能中。
摘要由CSDN通过智能技术生成

目录

备忘录模式(Memento)

UML图

示例代码

适用场景

优缺点

备忘录模式和原型模式

例子——游戏进度存档

例子——象棋中的悔棋


备忘录模式(Memento)

本质:保存和恢复内部状态

备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以后就可以利用保存的状态实施恢复。

为什么要增加一个备忘录类?

如果在Originator类中再增加一个方法来保存这个状态,则是对单一职责原则的一种破坏。

在游戏存档例子中,Gamerole类的职责就是打boss,而保留和恢复原始状态则应该由另外一个类来承担,那我们把这个类取名就叫做备忘录

UML图

在这里插入图片描述
Originator(发起人):需要被存储和恢复状态的角色

  • 创建一个备忘录,存储自己的当前内部状态
  • 使用备忘录来恢复自己的内部状态

Memento(备忘录):(类的设计参考发起人)

存储发起人的内部状态,根据实际需要确定备忘录类中的属性。

Caretaker(管理者):

存储一个或多个备忘录对象,但只负责存储,所以不能修改对象,也无须知道对象的实现细节。

存储多个备忘录对象时,可以使用list+泛型

示例代码

//发起人类
public class Originator {
	private String state;

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}
	
	public Memento CreateMemento() {
		return new Memento(state);
	}
	
    //恢复状态
	public void SetMemento(Memento memento) {
		state=memento.getState();
	}

	public void show() {
		System.out.println("state:"+state);
	}
}
//备忘录类
public class Memento {
	private String state;

	public Memento(String state) {
		super();
		this.state = state;
	}

	public String getState() {
		return state;
	}
	
}
//管理者类
public class CareTaker {
	private Memento memento;

	public Memento getMemento() {
		return memento;
	}
	
	public void setMemento(Memento memento) {
		this.memento = memento;
	}
	
}
public class Main {

	public static void main(String[] args) {
		Originator o=new Originator();
		o.setState("ON");//初始状态
		o.show();
		
		CareTaker c=new CareTaker();
		c.setMemento(o.CreateMemento());//保存状态
		
		o.setState("OFF");//改变状态
		o.show();
		
		o.SetMemento(c.getMemento());//恢复初始状态
		o.show();
	}

}

适用场景

保存一个对象在某一个时刻的全部或部分状态,在以后需要时,把该对象恢复到先前的状态

优缺点

优点:

  • 把发起人内部信息对外屏蔽,恰当地保持封装的边界:有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取
  • 简化了发起人类:发起人不需要管理和保存其内部状态的一个个版本,客户端可以自行管理需要状态的版本。
  • 当发起人对象的状态改变无效时,可以使用备忘录将状态复原。

缺点:

  • 如果发起人对象的状态需要完整地存储到备忘录对象中,那么在备忘录对象可能会消耗很多资源。
  • 管理者存储备忘录对象时,可能不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很大。

备忘录模式和原型模式

可以组合使用

在发起人对象创建备忘录对象时,如果发起人对象中全部或者大部分的状态都需要保存,一个简洁的方式就是直接克隆一个发起人对象。这时备忘录对象里存的是一个发起人对象的实例。

例子——游戏进度存档

public class GameRole {
	private int vit;//生命力
	private int atk;//攻击力
	private int def;//防御力
	
	//设置初始状态
	public void setInitState() {
		this.vit=100;
		this.atk=100;
		this.def=100;
	}
	
	//设置战后状态
	public void fight() {
		this.vit=0;
		this.atk=0;
		this.def=0;
	}
	
	//保存状态
	public RoleStateMemento saveState() {
		return new RoleStateMemento(vit,atk,def);
	}

	//恢复状态
	public void RecoverState(RoleStateMemento memento) {
		this.vit=memento.getVit();
		this.atk=memento.getAtk();
		this.def=memento.getDef();
	}

	
	//显示状态
	public void display() {
		System.out.println("vit=" + vit + ", atk=" + atk + ", def=" + def );
	}
	
}
//角色状态存储箱
public class RoleStateMemento {
	private int vit;//生命力
	private int atk;//攻击力
	private int def;//防御力
	
	public RoleStateMemento(int vit, int atk, int def) {
		super();
		this.vit = vit;
		this.atk = atk;
		this.def = def;
	}
	
	public int getVit() {
		return vit;
	}

	public void setVit(int vit) {
		this.vit = vit;
	}

	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;
	}
	
}
//角色状态管理者
public class RoleStateCareTaker {
	private RoleStateMemento memento;

	public RoleStateMemento getMemento() {
		return memento;
	}

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

}
public class Main {
	public static void main(String[] args) {
		//大战前
		GameRole lxy=new GameRole();
		lxy.setInitState();
		lxy.display();
		
		//保存进度
		RoleStateCareTaker state1=new RoleStateCareTaker();
		state1.setMemento(lxy.saveState());
		
		//大战后
		lxy.fight();
		lxy.display();
		
		//恢复原状态
		lxy.RecoverState(state1.getMemento());
		lxy.display();
	}

}

例子——象棋中的悔棋

package com.chess;

//发起人
public class ChessRole {
	private int x;
	private int y;
	private String name;
	private String color;
	
	public ChessRole(int x, int y, String name, String color) {
		super();
		this.x = x;
		this.y = y;
		this.name = name;
		this.color = color;
	}

	public ChessMemento createMemento() {
		return new ChessMemento(x,y,name,color);
	}
	
	public void getMemento(ChessMemento memento) {
		if(memento==null)return;
		this.x=memento.getX();
		this.y=memento.getY();
		this.name=memento.getName();
		this.color=memento.getColor();
	}

	public void setState(int x, int y, String name, String color) {
		this.x=x;
		this.y=y;
		this.name = name;
		this.color = color;
	}
	public void show() {
		System.out.println("坐标:x=" + x + ", y=" + y + ", name=" + name + ", color=" + color);
	}
	
}
package com.chess;

public class ChessMemento {
	private int x;
	private int y;
	private String name;
	private String color;
	
	public ChessMemento(int x, int y, String name, String color) {
		super();
		this.x = x;
		this.y = y;
		this.name = name;
		this.color = color;
	}

	public int getX() {
		return x;
	}

	public int getY() {
		return y;
	}

	public String getName() {
		return name;
	}

	public String getColor() {
		return color;
	}

}
package com.chess;

import java.util.ArrayList;

public class ChessCareTaker {
	private ArrayList<ChessMemento> list=new ArrayList<ChessMemento>();

	public ChessCareTaker() {
		list=new ArrayList<ChessMemento>();
	}
	
	public void addMemento(ChessMemento memento) {
		list.add(memento);
	}
	
	public ChessMemento huiqi() {
		if(list.isEmpty()) {
			System.out.println("无法悔棋");
			return null;
		}
		else {
			int index=list.size();
			ChessMemento memento=(ChessMemento)list.get(index-1);
			list.remove(index-1);
			return memento;
		}
	}

}
package com.chess;

public class Main {

	public static void main(String[] args) {
		ChessRole c1=new ChessRole(0,0,"马1","红方");
		ChessCareTaker ct1=new ChessCareTaker();
		ct1.addMemento(c1.createMemento());
		c1.show();
		
		c1.setState(1, 2, "马1", "红方");
		ct1.addMemento(c1.createMemento());
		c1.show();
		
		c1.setState(3, 5, "象2", "红方");
		c1.show();
		
		System.out.println("悔棋一步:");
		c1.getMemento(ct1.huiqi());
		c1.show();
		System.out.println("悔棋二步:");
		c1.getMemento(ct1.huiqi());
		c1.show();
		
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值