# Notes: Go Design Patterns - Memento Pattern

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

```
