Notes: Go Design Patterns - Memento Pattern

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

ยท

2 min read

Table of contents

No heading

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())
}
ย