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

目录

备忘录模式(Memento)

UML图

示例代码

适用场景

优缺点

备忘录模式和原型模式

例子——游戏进度存档

例子——象棋中的悔棋


备忘录模式(Memento)

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

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

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

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

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

UML图

23种设计模式——备忘录模式_第1张图片
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();
	}

}

例子——象棋中的悔棋

23种设计模式——备忘录模式_第2张图片

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 list=new ArrayList();

	public ChessCareTaker() {
		list=new ArrayList();
	}
	
	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();
		
	}

}

你可能感兴趣的:(设计模式,设计模式,备忘录模式)