This is the seventh day of my participation in the August More text Challenge. For details, see: August More Text Challenge
When I learned the memo mode, I was very happy. This is not the game backup! When the game is closed, it reopens and picks up where it left off. But I never got into the game industry and never had a chance to use the memo model.
UML class diagrams location: www.processon.com/view/link/6…
The link to this article is github.com/shidawuhen/…
Definition 1.
1.1 Memorandum Mode
Memo pattern: Capture an object’s internal state and save it outside of the object without breaking encapsulation. You can then restore the object to its previously saved state.
UML:
1.2 analysis
By definition, it’s easy to understand, except that it doesn’t break encapsulation. As for not breaking encapsulation, I think there are two things:
-
The memo was created by Originator itself
-
The memo should only get the relevant interface, not modify the relevant interface
What is Caretaker used? Instead of one memo, Caretaker can be multiple and Caretaker means multiple memos are managed.
Originator Uses CreateMemento to create a memo and SetMemento to restore it to the specified state.
Why do you use a Memento instead of an Originator? This is because the Memento only holds data. If you save the Originator, you will save the functionality as well, which should not be saved.
Another benefit of keeping only the data is that even if the data is parsed, you don’t know how to use it. Only the Originator knows the real formula.
2. Application scenario
Games, or documents, often use backup related features. When playing the game to fight the Boss, will generally do a save, failed to start again. The document also has the rollback function, otherwise the graduation thesis wrote the power, all the content into nothing, how sad.
I’ve written before about the Go Design Pattern (22)- The State Pattern, which is also a simple little game that serves as the basis for implementing a memo pattern.
3. Code implementation
package main
import (
"container/list"
"fmt"
)
/** * @author: Jason Pang */
type Memento struct {
mario *Mario
}
func (m *Memento) GetMario(a) *Mario {
return m.mario
}
/** * @author: Jason Pang */
type Caretaker struct {
stack *list.List
}
/** * @author: Jason Pang * @description: Save the memo * @receiver c * @param m */
func (c *Caretaker) Save(m *Memento) {
c.stack.PushBack(m)
}
/** * @author: Jason Pang * @description: @receiver c * @return *Memento */
func (c *Caretaker) Pop(a) *Memento {
e := c.stack.Back()
c.stack.Remove(e)
return e.Value.(*Memento)
}
type Mario struct {
score int64
status MarioStatus
}
/** * @author: Jason Pang * @description: @receiver m */
func (m *Mario) ShowInfo(a) {
m.status.Name()
fmt.Println("Current score is :", m.score)
}
/** * @author: Jason Pang * @description: Create memos * @receiver m */
func (m *Mario) CreateMemento(a) *Memento {
return &Memento{
mario: &Mario{
score: m.score,
status: m.status,
},
}
}
/** * @author: Jason Pang * @description: restore data * @receiver m * @param mem */
func (m *Mario) SetMemento(mem *Memento) {
m.score = mem.mario.score
m.status = mem.mario.status
}
type MarioStatus interface {
Name()
ObtainMushroom()
ObtainCape()
MeetMonster()
SetMario(mario *Mario)
}
/** * @author: Jason Pang * @description */
type SmallMarioStatus struct {
mario *Mario
}
/** * @author: Jason Pang * @description: Set Mario * @receiver s * @param Mario */
func (s *SmallMarioStatus) SetMario(mario *Mario) {
s.mario = mario
}
func (s *SmallMarioStatus) Name(a) {
fmt.Println("Little Mario")}/** * @author: Jason Pang * @description: @receiver s */
func (s *SmallMarioStatus) ObtainMushroom(a) {
s.mario.status = &SuperMarioStatus{
mario: s.mario,
}
s.mario.score += 100
}
/** * @author: Jason Pang * @description: @receiver s */
func (s *SmallMarioStatus) ObtainCape(a) {
s.mario.status = &CapeMarioStatus{
mario: s.mario,
}
s.mario.score += 200
}
/** * @author: Jason Pang * @description: @receiver s */
func (s *SmallMarioStatus) MeetMonster(a) {
s.mario.score -= 100
}
/** * @author: Jason Pang * @description: Super Mario */
type SuperMarioStatus struct {
mario *Mario
}
/** * @author: Jason Pang * @description: Set Mario * @receiver s * @param Mario */
func (s *SuperMarioStatus) SetMario(mario *Mario) {
s.mario = mario
}
func (s *SuperMarioStatus) Name(a) {
fmt.Println("Super Mario")}/** * @author: Jason Pang * @description: @receiver s */
func (s *SuperMarioStatus) ObtainMushroom(a){}/** * @author: Jason Pang * @description: @receiver s */
func (s *SuperMarioStatus) ObtainCape(a) {
s.mario.status = &CapeMarioStatus{
mario: s.mario,
}
s.mario.score += 200
}
/** * @author: Jason Pang * @description: @receiver s */
func (s *SuperMarioStatus) MeetMonster(a) {
s.mario.status = &SmallMarioStatus{
mario: s.mario,
}
s.mario.score -= 200
}
/** * @author: Jason Pang * @description: Mario */
type CapeMarioStatus struct {
mario *Mario
}
/** * @author: Jason Pang * @description: Set Mario * @receiver s * @param Mario */
func (c *CapeMarioStatus) SetMario(mario *Mario) {
c.mario = mario
}
func (c *CapeMarioStatus) Name(a) {
fmt.Println(Cape Mario)}/** * @author: Jason Pang * @description: @receiver c */
func (c *CapeMarioStatus) ObtainMushroom(a){}/** * @author: Jason Pang * @description: @receiver c */
func (c *CapeMarioStatus) ObtainCape(a){}/** * @author: Jason Pang * @description: @receiver c */
func (c *CapeMarioStatus) MeetMonster(a) {
c.mario.status = &SmallMarioStatus{
mario: c.mario,
}
c.mario.score -= 200
}
func main(a) {
caretaker := &Caretaker{
stack: list.New(),
}
mario := Mario{
status: &SmallMarioStatus{},
score: 0,
}
mario.status.SetMario(&mario)
mario.status.Name()
fmt.Println("------------------- get mushroom \n")
mario.status.ObtainMushroom()
mario.status.Name()
fmt.Println("------------------- get cape \n")
mario.status.ObtainCape()
fmt.Println("------------------- back up, need to hit strange, the current status is \n")
mario.ShowInfo()
caretaker.Save(mario.CreateMemento())
fmt.Println("------------------- begin to hit the strange \n")
mario.status.Name()
fmt.Println("------------------- Meet the Monster \n")
mario.status.MeetMonster()
fmt.Println("------------------- failed to hit monsters, status \n")
mario.ShowInfo()
fmt.Println("------------------- to restore status, re-hit monster \n")
mario.SetMemento(caretaker.Pop())
mario.ShowInfo()
}
Copy the code
Output:
➜ myproject go run main.go
Small Mario
——————- Get the mushrooms
Super Mario
——————- Get the cape
——————- backup, to hit strange, the current status is
Cape Mario
Current score: 300
——————- start to fight strange
Cape Mario
——————- Meet the monster
——————- Failed to hit the monster, the current status is
Small Mario
The current score is 100
——————- Restore the status and refight the monster
Cape Mario
Current score: 300
conclusion
I think that’s one reason why people don’t want to use design patterns. However, when used, it is found that this design pattern can conveniently achieve many functions, which is why some people want to use design pattern.
The memo pattern, while not commonly used, can be helpful in the right scenario.
The last
If you like my article, you can follow my public number (programmer Malatang)
My personal blog is shidawuhen.github. IO /
Review of previous articles:
-
Design patterns
-
recruitment
-
thinking
-
storage
-
The algorithm series
-
Reading notes
-
Small tools
-
architecture
-
network
-
The Go