Memento Design Pattern in Go

1. Definition

The Memento Design Pattern provides a way to capture an object's internal state such that it can be restored to this state later, without violating the principles of encapsulation.

2. Problem Statement

How can we implement an undo/redo mechanism or create checkpoints for an object's state without exposing the internal details of the object?

3. Solution

Create a separate memento object that privately stores the state of the main object. The main object can create snapshots of its state in memento objects, and it can also restore its state from a memento when needed.

4. Real-World Use Cases

1. Editor applications where users need to undo/redo actions.

2. Game systems where players can save their progress and load it later.

3. Database systems that need to maintain transaction logs for rollback operations.

5. Implementation Steps

1. Define the Originator, Memento, and Caretaker.

2. The Originator creates a memento containing a snapshot of its current internal state.

3. The Caretaker uses the memento to restore the Originator to its previous state.

6. Implementation in Go

// Memento stores the state of the Originator
type Memento struct {
	state string
}
func (m *Memento) getState() string {
	return m.state
}
// Originator has an internal state and creates Mementos
type Originator struct {
	state string
}
func (o *Originator) createMemento() *Memento {
	return &Memento{state: o.state}
}
func (o *Originator) restore(m *Memento) {
	o.state = m.getState()
}
// Caretaker keeps track of multiple mementos
type Caretaker struct {
	mementos []*Memento
}
func (c *Caretaker) addMemento(m *Memento) {
	c.mementos = append(c.mementos, m)
}
func (c *Caretaker) getMemento(index int) *Memento {
	return c.mementos[index]
}
// Client code
func main() {
	originator := &Originator{state: "State1"}
	caretaker := &Caretaker{}
	caretaker.addMemento(originator.createMemento())
	originator.state = "State2"
	caretaker.addMemento(originator.createMemento())
	originator.state = "State3"
	// Restore to State2
	originator.restore(caretaker.getMemento(1))
	fmt.Println("Restored State:", originator.state)
}

Output:

Restored State: State2

Explanation:

1. The Originator has an internal state and can create mementos to save its state.

2. The Caretaker is responsible for storing and retrieving saved mementos.

3. In the client code, we changed the state of the Originator multiple times and saved its states in mementos. Later, we restored the Originator to one of its previous states using a memento.

7. When to use?

The Memento Pattern is useful when:

1. You want to provide a mechanism for capturing and restoring an object's state so that its previous states can be restored without revealing its implementation.

2. Snapshots of (some portion of) an object's state need to be saved so that they can be restored later.

3. Direct exposure of an object's state would violate encapsulation.


Comments