【設(shè)計模式】通過游戲存檔了解備忘錄模式
背景
你(Caretaker)在玩一個游戲,可以對游戲進行存檔(Memento),以便后面遇到不符合預(yù)期的游戲場景,通過存檔管理(Originator)恢復(fù)。
模式定義
Without violating encapsulation,capture and externalize an object's internal state so that the object can be restored to this state later.
在不違反封裝的情況下,捕獲并外部化對象的內(nèi)部狀態(tài),以便以后可以將對象恢復(fù)到該狀態(tài)。
模式結(jié)構(gòu)
模式實現(xiàn)
1.定義游戲狀態(tài)類
package com.example.designpattern.memento.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 游戲狀態(tài)
*
* @author hongcunlin
*/
@Data
@AllArgsConstructor
public class GameState {
/**
* 經(jīng)驗值
*/
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 {
/**
* 經(jīng)驗值
*/
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.實現(xiàn)游戲存檔管理接口
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);
}
}
可以看到,游戲是可以正常會退到存檔的內(nèi)容的
回顧
本文通過游戲的存檔、回退存檔,抽象出與符合的設(shè)計模式——備忘錄模式。同時,與傳統(tǒng)Java的說教不同,本次的實現(xiàn)基于企業(yè)開發(fā)必用的Spring框架,貼近實際開發(fā)場景。
不過備忘錄模式在實際開發(fā)中的應(yīng)用并不多,很少有數(shù)據(jù)存儲在服務(wù)器容器運行的內(nèi)存中,而是會將數(shù)據(jù)存儲到專門的數(shù)據(jù)庫中,如磁盤型數(shù)據(jù)庫MySQL,內(nèi)存型數(shù)據(jù)庫Redis等。