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:

  1. The memo was created by Originator itself

  2. 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:

  1. Design patterns

  2. recruitment

  3. thinking

  4. storage

  5. The algorithm series

  6. Reading notes

  7. Small tools

  8. architecture

  9. network

  10. The Go