Memento Design Pattern in Swift

1. Definition

The Memento pattern allows for the ability to restore an object to its previous state, which can be useful for "undo" functionality.

2. Problem Statement

Imagine a text editor where you want to provide an "undo" feature. Overwriting the previous states or constantly copying every version of the text can be inefficient and complex.

3. Solution

The Memento pattern captures the internal state of an object without exposing its internal structure. Later, this captured state can be restored without the originator having direct access to its saved state.

4. Real-World Use Cases

1. Undo and redo functionality in software tools.

2. Taking snapshots of system configurations.

3. Save and restore points in video games.

5. Implementation Steps

1. Create a Memento class that will store the internal state of the Originator class.

2. Implement the Originator class that creates a memento containing a snapshot of its current internal state and can restore its state from a memento.

3. Optionally, use a Caretaker class that maintains a list of mementos.

6. Implementation in Swift Programming

// Memento class
class Memento {
    private let state: String
    init(state: String) {
        self.state = state
    }
    func getState() -> String {
        return state
    }
}
// Originator class
class Originator {
    private var state: String = ""
    func set(state: String) {
        self.state = state
    }
    func saveToMemento() -> Memento {
        return Memento(state: state)
    }
    func restoreFromMemento(memento: Memento) {
        state = memento.getState()
    }
    func showState() -> String {
        return state
    }
}
// Caretaker class
class Caretaker {
    private var mementos: [Memento] = []
    func addMemento(memento: Memento) {
        mementos.append(memento)
    }
    func getMemento(at index: Int) -> Memento? {
        return mementos.indices.contains(index) ? mementos[index] : nil
    }
}
// Usage
let originator = Originator()
let caretaker = Caretaker()
originator.set(state: "State1")
originator.set(state: "State2")
caretaker.addMemento(memento: originator.saveToMemento())
originator.set(state: "State3")
caretaker.addMemento(memento: originator.saveToMemento())
originator.set(state: "State4")
originator.restoreFromMemento(memento: caretaker.getMemento(at: 1)!)
let output = originator.showState()

Output:

State3

Explanation:

1. We have a Memento class to store the state of the Originator.

2. The Originator changes its state over time and can save its state to a memento or restore its state from a memento.

3. The Caretaker class keeps track of multiple mementos but doesn't operate on their content.

7. When to use?

Use the Memento pattern when:

1. You want to provide a mechanism to capture an object's internal state so it can be restored later.

2. You need a direct interface for obtaining the state of an object.

3. Internal details of an object should be hidden from other objects.


Comments