Memento Design Pattern in Kotlin

1. Definition

The Memento Design Pattern provides a mechanism to capture an object's internal state such that it can be restored to this state at a later time. This pattern involves three roles: Originator, Caretaker, and Memento.

2. Problem Statement

Consider a scenario where we want to implement an undo mechanism in a software application. Every operation modifies the state, and to revert, we must know the previous states of the application, but without violating the encapsulation principle.

3. Solution

The Memento pattern achieves this by having the Originator create a snapshot of its internal state and then handing it to a Caretaker object. The Caretaker is responsible for keeping the mementos, but it doesn't modify or examine them.

4. Real-World Use Cases

1. Undo and redo operations in text editors.

2. Snapshot or restore points in virtual machine management.

3. Game save and load states.

5. Implementation Steps

1. Define the Memento, which stores the state of the Originator.

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

3. The Caretaker takes and keeps these mementos without knowing their content.

6. Implementation in Kotlin

// Step 1: Memento class
data class Memento(val state: String)
// Step 2: Originator class
class Originator(var state: String) {
    fun createMemento(): Memento = Memento(state)
    fun restore(memento: Memento) { this.state = memento.state }
}
// Step 3: Caretaker class
class Caretaker {
    private val mementoList = mutableListOf<Memento>()
    fun add(memento: Memento) = mementoList.add(memento)
    fun get(index: Int): Memento = mementoList[index]
}
// Testing the implementation
fun main() {
    val originator = Originator("Initial State")
    val caretaker = Caretaker()
    caretaker.add(originator.createMemento())
    originator.state = "State #1"
    caretaker.add(originator.createMemento())
    originator.state = "State #2"
    originator.restore(caretaker.get(0))
    println(originator.state)  // Should print "Initial State"
}

Output:

Initial State

Explanation:

1. Memento holds the internal state of the Originator object. In our case, it's a simple string state, but it could be more complex.

2. Originator creates a memento using createMemento() and can also restore its state using a given memento through the restore() method.

3. Caretaker holds a list of mementos but never modifies or directly accesses their contents.

4. In the testing phase, we change the state of the Originator a couple of times and then use a stored memento to revert its state. We print the state to verify that the Originator has indeed returned to its initial state.

7. When to use?

Use the Memento Pattern when:

1. You need to implement a snapshot mechanism to roll back states or implement undo/redo operations.

2. You want to save states of objects for later use without exposing their internals.

3. You want to ensure the encapsulation integrity of an object by preventing other objects from accessing its internal state directly.


Comments