背景
你(Caretaker)在玩一个游戏,可以对游戏进行存档(Memento),以便后面遇到不符合预期的游戏场景,通过存档管理(Originator)恢复。
模式定义
Without violating encapsulation,capture and externalize an object's internal state so that the object can be restored to this state later.
在不违反封装的情况下,捕获并外部化对象的内部状态,以便以后可以将对象恢复到该状态。
模式结构
模式实现
1.定义游戏状态类
package com.example.designpattern.memento.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 游戏状态
*
* @author hongcunlin
*/
@Data
@AllArgsConstructor
public class GameState {
/**
* 经验值
*/
private int exp;
/**
* 等级
*/
private int level;
/**
* 存档
*
* @return 存档
*/
public GameMemento save() {
return new GameMemento(exp, level);
}
/**
* 加载存档
*
* @param gameMemento 存档
*/
public void restore(GameMemento gameMemento) {
exp = gameMemento.getExp();
level = gameMemento.getLevel();
}
}
2.定义游戏存档类
package com.example.designpattern.memento.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 游戏存档
*
* @author hongcunlin
*/
@Data
@AllArgsConstructor
public class GameMemento {
/**
* 经验值
*/
private int exp;
/**
* 等级
*/
private int level;
}
3.定义游戏存档管理接口
package com.example.designpattern.memento.manager;
import com.example.designpattern.memento.domain.GameMemento;
/**
* 游戏存档管理
*
* @author hongcunlin
*/
public interface GameSaveManger {
/**
* 保持存档
*
* @param memento 存档
*/
void addSave(GameMemento memento);
/**
* 获取存档
*
* @param index 索引
* @return 存档
*/
GameMemento getSave(int index);
}
4.实现游戏存档管理接口
package com.example.designpattern.memento.manager.impl;
import com.example.designpattern.memento.domain.GameMemento;
import com.example.designpattern.memento.manager.GameSaveManger;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 游戏管理
*
* @author hongcunlin
*/
@Component("gameSaveManger")
public class GameSaveMangerImpl implements GameSaveManger {
/**
* 存档列表
*/
private final List<GameMemento> saves = new ArrayList<>();
/**
* 保持存档
*
* @param memento 存档
*/
@Override
public void addSave(GameMemento memento) {
saves.add(memento);
}
/**
* 获取存档
*
* @param index 索引
* @return 存档
*/
@Override
public GameMemento getSave(int index) {
return saves.get(index);
}
}
5.测试
package com.example.designpattern.memento;
import com.example.designpattern.memento.domain.GameState;
import com.example.designpattern.memento.manager.GameSaveManger;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
/**
* 备忘录模式测试
*
* @author hongcunlin
*/
@SpringBootTest
public class DesignPatternTest {
/**
* 游戏存档管理
*/
@Resource(name = "gameSaveManger")
private GameSaveManger gameSaveManger;
@Test
public void test() {
// 开始游戏
GameState gameState = new GameState(1, 1);
// 存档游戏
gameSaveManger.addSave(gameState.save());
// 玩游戏
gameState.setExp(2);
gameState.setLevel(2);
// 加载存档
gameState.restore(gameSaveManger.getSave(0));
System.out.println(gameState);
}
}
可以看到,游戏是可以正常会退到存档的内容的
回顾
本文通过游戏的存档、回退存档,抽象出与符合的设计模式——备忘录模式。同时,与传统Java的说教不同,本次的实现基于企业开发必用的Spring框架,贴近实际开发场景。
不过备忘录模式在实际开发中的应用并不多,很少有数据存储在服务器容器运行的内存中,而是会将数据存储到专门的数据库中,如磁盘型数据库MySQL,内存型数据库Redis等。