Notes: Go Design Patterns - Memento Pattern
This blog contains the implementation of Memento design pattern by creating snapshots of Orders and storing them in Memento and then in History
Table of contents
No headings in the article.
Memento pattern is used to save state and restore state of an object to a previous state. As your application is progressing, you may want to save state snapshots in your application and restore back to those snapshots later. This is a behavioral pattern.
In our example, we want to store snapshots of the Order
object. To store the snapshots, we create memento class containing Order
object with GetSavedOrder
method to get the previous state stored in memento.
type Memento struct {
order *Order
}
func (m *Memento) GetSavedOrder() *Order {
return m.order
}
In Order
class, we add CreateMemento
and Restore
method to create and restore memeto respectively.
func (t *OrderWrapper) CreateMemento() *Memento {
return &Memento{order: t.order}
}
func (t *OrderWrapper) Restore(m *Memento) {
t.order = m.GetSavedOrder()
}
Now to extend functionality we can add history which can store all the mementos as an array. This way we'll be able to move across different stages of order with multiple saved snapshots. History
can have Save
and Get
methods to save memento and get memento at any index respectively.
type History struct {
history []*Memento
}
func (h *History) Save(m *Memento) {
h.history = append(h.history, m)
}
func (h *History) Get(index int) *Memento {
return h.history[index]
}
Complete working code where you can see the complete result:
package main
import "fmt"
type Order struct {
Id string
Client string
Amount float64
Status bool
}
type OrderWrapper struct {
order *Order
}
func NewOrderWrapper() *OrderWrapper {
return &OrderWrapper{}
}
// to create memento snapshot
func (t *OrderWrapper) CreateMemento() *Memento {
return &Memento{order: t.order}
}
// to restore to the passed memento snapshot
func (t *OrderWrapper) Restore(m *Memento) {
t.order = m.GetSavedOrder()
}
func (t *OrderWrapper) Set(order *Order) {
t.order = order
}
func (t *OrderWrapper) Get() *Order {
return t.order
}
// memento addition
// * memento cannot mutate as it's a snapshot
// so it has only get method
type Memento struct {
order *Order
}
func (m *Memento) GetSavedOrder() *Order {
return m.order
}
// saving history of memento snapshots
type History struct {
history []*Memento
}
func NewHistory() *History {
return &History{make([]*Memento, 0)}
}
func (h *History) Save(m *Memento) {
h.history = append(h.history, m)
}
func (h *History) Get(index int) *Memento {
return h.history[index]
}
func main() {
history := NewHistory()
orderwrapper := NewOrderWrapper()
order := Order{
Id: "ORD001",
Client: "a6dba009adfe",
Amount: 4.99,
Status: false,
}
orderwrapper.Set(&order)
history.Save(orderwrapper.CreateMemento())
changedOrder := Order{
Id: "ORD001",
Client: "a6dba009adfe",
Amount: 6.79,
Status: true,
}
orderwrapper.Set(&changedOrder)
history.Save(orderwrapper.CreateMemento())
fmt.Printf("%#v\n", orderwrapper.Get())
orderwrapper.Restore(history.Get(0))
fmt.Printf("%#v\n", orderwrapper.Get())
orderwrapper.Restore(history.Get(1))
fmt.Printf("%#v\n", orderwrapper.Get())
}