mirror of
https://github.com/crazybber/go-pattern-examples.git
synced 2024-11-25 05:06:03 +03:00
finish memento pattern
This commit is contained in:
parent
c988ffc8ff
commit
2bd8e1560b
@ -26,9 +26,9 @@
|
||||
+ [x] [模板方法模式(Template Method)](./behavior/05_template_method)
|
||||
+ [x] [策略模式(Strategy)](./behavior/12_strategy)
|
||||
+ [ ] [WIP][状态模式(State)](./behavior/behavior16_state)
|
||||
+ [ ] [WIP][备忘录模式(Memento)](./behavior/09_memento)
|
||||
+ [ ] [备忘录模式(Memento)](./behavior/09_memento)
|
||||
+ [x] [访问者模式(Visitor)](./behavior/07_visitor)
|
||||
+ [ ] [WIP][解释器模式(Interpreter)](./behavior/08_interpreter)
|
||||
+ [x] [解释器模式(Interpreter)](./behavior/08_interpreter)
|
||||
+ [x] [职责链模式(Chain of Responsibility)](./behavior/06_chain_of_responsibility)
|
||||
|
||||
|
||||
|
@ -1,7 +1,16 @@
|
||||
# 备忘录模式
|
||||
|
||||
备忘录模式用于保存程序内部状态到外部,又不希望暴露内部状态的情形。
|
||||
备忘录模式,又叫快照模式,备份模式,用于在不暴露内部状态的情况下,保存程序内部状态到外部。
|
||||
|
||||
程序内部状态使用窄接口船体给外部进行存储,从而不暴露程序实现细节。
|
||||
主要保存的是数据(也就是状态),这些数据可以是静态数据,也可以是一个操作描述。
|
||||
|
||||
备忘录模式同时可以离线保存内部状态,如保存到数据库,文件等。
|
||||
在CQRS中的事件溯源模式(Event Sourcing)中,就是保存事件的操作(包含操作参数集)到持久化数据中,以达到事件回溯的目的.
|
||||
|
||||
现实生活中涉及备份和快照的例子就太多了,日常的打游戏存档,下次玩的时候,读取存档,读取进度,也是这个模式。
|
||||
|
||||
|
||||
该模式中有三个关键角色:
|
||||
|
||||
1. 发起人角色 Originator: 负责记录当前的内部状态,提供当前状态数据,并负责恢复备忘录数据。
|
||||
2. 备忘录角色 Memento : 负责存放发起人对象某个时刻的内部状态,这就是要保存的数据结构类型。
|
||||
3. 管理者角色 Caretaker: 负责保存备忘录对象。
|
||||
|
@ -1,35 +1,65 @@
|
||||
package memento
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Memento interface{}
|
||||
////////////////////////////////
|
||||
//使用游戏玩家的角色存档和读取的例子
|
||||
|
||||
type Game struct {
|
||||
hp, mp int
|
||||
//GamePlayer 是一个Originator 提供当前的游戏状态
|
||||
type GamePlayer struct {
|
||||
hp, mp, role, level int //血量,魔法值,当前关卡
|
||||
}
|
||||
|
||||
type gameMemento struct {
|
||||
hp, mp int
|
||||
//RoleStatusMemento 一条备忘数据,存放瞬时状态的数据结构,一个数据结构
|
||||
type RoleStatusMemento struct {
|
||||
tag string //存档记录本身的名称,以便下次识别读取
|
||||
hp, mp, level int //血量,魔法值,角色类型,当前关卡,
|
||||
timeMark string //存档的可视化时间
|
||||
}
|
||||
|
||||
func (g *Game) Play(mpDelta, hpDelta int) {
|
||||
g.mp += mpDelta
|
||||
g.hp += hpDelta
|
||||
//RoleStatusCaretaker 负责保存角色当前的状态数据,提供存取能力
|
||||
//RoleStatusCaretaker 也是占内存/存储的地方,如果不停的读取,IO压力会变大的很大
|
||||
type RoleStatusCaretaker struct {
|
||||
memens map[string]*RoleStatusMemento
|
||||
}
|
||||
|
||||
func (g *Game) Save() Memento {
|
||||
return &gameMemento{
|
||||
//SaveStatus 保存当前角色的游戏状态
|
||||
func (r *RoleStatusCaretaker) SaveStatus(item *RoleStatusMemento) {
|
||||
r.memens[item.tag] = item
|
||||
fmt.Printf("Game File %s Saved at %s\n", item.tag, item.timeMark)
|
||||
}
|
||||
|
||||
//RetriveStatus 提供需要的状态
|
||||
func (r *RoleStatusCaretaker) RetriveStatus(savedTag string) *RoleStatusMemento {
|
||||
return r.memens[savedTag]
|
||||
|
||||
}
|
||||
|
||||
//Create 创建游戏的当前档案存档
|
||||
func (g *GamePlayer) Create(tagName string) *RoleStatusMemento {
|
||||
|
||||
return &RoleStatusMemento{
|
||||
tag: tagName,
|
||||
hp: g.hp,
|
||||
mp: g.mp,
|
||||
level: g.level,
|
||||
timeMark: time.Now().String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Game) Load(m Memento) {
|
||||
gm := m.(*gameMemento)
|
||||
g.mp = gm.mp
|
||||
g.hp = gm.hp
|
||||
//Load 载入存档,恢复数据
|
||||
func (g *GamePlayer) Load(rm *RoleStatusMemento) {
|
||||
g.mp = rm.mp
|
||||
g.hp = rm.hp
|
||||
g.level = rm.level
|
||||
|
||||
fmt.Printf("Game Profile had been restored to %s : %s\n", rm.tag, rm.timeMark)
|
||||
}
|
||||
|
||||
func (g *Game) Status() {
|
||||
fmt.Printf("Current HP:%d, MP:%d\n", g.hp, g.mp)
|
||||
//Status 玩家角色的当前状态
|
||||
func (g *GamePlayer) Status() {
|
||||
fmt.Printf("Current Level :%d HP:%d, MP:%d\n", g.level, g.hp, g.mp)
|
||||
}
|
||||
|
@ -1,22 +1,44 @@
|
||||
package memento
|
||||
|
||||
func ExampleGame() {
|
||||
game := &Game{
|
||||
hp: 10,
|
||||
mp: 10,
|
||||
}
|
||||
|
||||
game.Status()
|
||||
progress := game.Save()
|
||||
|
||||
game.Play(-2, -3)
|
||||
game.Status()
|
||||
|
||||
game.Load(progress)
|
||||
game.Status()
|
||||
|
||||
// Output:
|
||||
// Current HP:10, MP:10
|
||||
// Current HP:7, MP:8
|
||||
// Current HP:10, MP:10
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestGameArchive(t *testing.T) {
|
||||
|
||||
gamerole := GamePlayer{hp: 1000, mp: 232, level: 20}
|
||||
|
||||
datakeeper := RoleStatusCaretaker{memens: make(map[string]*RoleStatusMemento)}
|
||||
|
||||
archive1 := gamerole.Create("第一次存档")
|
||||
|
||||
//交给管数据的人,存起来
|
||||
datakeeper.SaveStatus(archive1)
|
||||
|
||||
//模拟,随机玩会儿游戏
|
||||
time.Sleep(time.Millisecond * 1132)
|
||||
|
||||
//更新角色当前状态
|
||||
gamerole = GamePlayer{hp: 500, mp: 10, level: 30}
|
||||
|
||||
//看一下状态
|
||||
gamerole.Status()
|
||||
|
||||
archive2 := gamerole.Create("第二次存档")
|
||||
|
||||
//交给管数据的人,存起来
|
||||
datakeeper.SaveStatus(archive2)
|
||||
|
||||
//准备恢复第一次的存档
|
||||
|
||||
//查找档案
|
||||
restore1 := datakeeper.RetriveStatus("第一次存档")
|
||||
|
||||
//载入档案
|
||||
gamerole.Load(restore1)
|
||||
|
||||
//看一下状态
|
||||
gamerole.Status()
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user