Memento Pattern #

Dalam pengembangan perangkat lunak, mengelola perubahan state objek adalah hal penting, terutama ketika kita ingin memberikan kemampuan untuk undo/redo atau menyimpan snapshot dari sebuah objek. Salah satu pola desain (design pattern) yang membantu mengatasi masalah ini adalah Memento Pattern. Pola ini termasuk dalam kategori Behavioral Pattern, yang fokus pada komunikasi dan tanggung jawab antar objek.

Apa itu Memento Pattern? #

Memento Pattern adalah pola desain yang memungkinkan kita menyimpan snapshot dari state sebuah objek tanpa mengungkapkan implementasi internalnya. Objek yang ingin disimpan state-nya disebut Originator, sedangkan snapshot disimpan dalam objek Memento. Sebuah Caretaker bertugas menyimpan Memento dan mengembalikannya ke Originator saat dibutuhkan.

Komponen Utama #

  1. Originator: Objek utama yang state-nya ingin disimpan dan dipulihkan.
  2. Memento: Objek yang menyimpan snapshot state Originator.
  3. Caretaker: Objek yang bertanggung jawab menyimpan dan mengelola Memento.

Tujuan dari Pattern #

Tujuan utama Memento Pattern adalah:

  • Menyimpan snapshot dari state objek untuk memungkinkan undo/redo.
  • Menghindari pelanggaran prinsip encapsulation, karena internal state objek tidak diekspos ke luar.
  • Mempermudah pengelolaan perubahan state kompleks.

Kapan Cocok Digunakan? #

Memento Pattern cocok digunakan ketika:

  • Dibutuhkan kemampuan undo/redo (misalnya text editor atau game).
  • State objek kompleks dan tidak ingin diungkap ke luar.
  • Perubahan state harus dicatat secara temporer atau disimpan untuk rollback.

Contoh Implementasi (Golang) #

Berikut contoh implementasi sederhana Memento Pattern pada Golang.

package main

import "fmt"

// Originator
type Editor struct {
	content string
}

func (e *Editor) Write(text string) {
	e.content += text
}

func (e *Editor) GetContent() string {
	return e.content
}

func (e *Editor) Save() *EditorMemento {
	return &EditorMemento{state: e.content}
}

func (e *Editor) Restore(m *EditorMemento) {
	e.content = m.state
}

// Memento
type EditorMemento struct {
	state string
}

// Caretaker
type History struct {
	undos []*EditorMemento
}

func (h *History) Push(m *EditorMemento) {
	h.undos = append(h.undos, m)
}

func (h *History) Pop() *EditorMemento {
	if len(h.undos) == 0 {
		return nil
	}
	m := h.undos[len(h.undos)-1]
	h.undos = h.undos[:len(h.undos)-1]
	return m
}

func main() {
	editor := &Editor{}
	history := &History{}

	editor.Write("Hello")
	history.Push(editor.Save())

	editor.Write(", World")
	history.Push(editor.Save())

	fmt.Println("Current Content:", editor.GetContent())

	editor.Restore(history.Pop())
	fmt.Println("After Undo:", editor.GetContent())

	editor.Restore(history.Pop())
	fmt.Println("After Second Undo:", editor.GetContent())
}

Output #

Current Content: Hello, World
After Undo: Hello
After Second Undo:

Best Practices #

  • Gunakan dengan bijak: Jangan menyimpan state terlalu besar, karena bisa membebani memori.
  • Encapsulation tetap terjaga: Memento hanya menyimpan state yang diperlukan, jangan expose implementasi internal Originator.
  • Pertimbangkan immutability: Pastikan Memento tidak dapat diubah setelah dibuat.
  • Integrasi dengan undo/redo: Cocok digunakan dalam aplikasi yang membutuhkan rollback atau history.

Penutup #

  • Memento Pattern sering digunakan dalam aplikasi text editor, graphic editor, game, dan workflow engine.
  • Memento dapat dioptimalkan menggunakan lazy snapshot jika state objek sangat besar.
  • Dalam konteks database, pola ini mirip dengan transaction snapshot untuk rollback.

Memento Pattern membantu menjaga konsistensi state objek sambil tetap mempertahankan enkapsulasi, membuatnya menjadi pola desain penting untuk aplikasi yang membutuhkan undo/redo atau rollback history.

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact