Skip to content

Composite Command Memento

BrandonRobare edited this page Jun 2, 2026 · 1 revision

Composite, Command & Memento

Folder: 12-composite-command-memento

What it is

The last lab is the densest. It holds four programs that together cover five patterns. A genealogy tree uses Composite and Visitor. A text editor with undo uses Command. A second editor with checkpoint and rollback uses Memento. A merged editor combines Command, Memento, and Prototype.

Composite & Visitor

Folder file: genealogy.cpp

Composite intent. Compose objects into tree structures and let clients treat a single object and a group of objects the same way.

Visitor intent. Represent an operation to perform on the elements of a structure without changing their classes. New operations become new visitors.

How this code does it. Person is the component. Man is a leaf, and Woman holds a vector of children, which makes the tree. Both implement accept, and a Woman forwards accept to each child, so visiting the root walks the whole family. The operations are visitors: NamePrinter prints each person's name, and MiddleNameVisitor (which I wrote) gives each person a middle name drawn from a parent. Adding an operation means adding a visitor, not editing Person.

classDiagram
    class Person {
        +accept(PersonVisitor*)* void
        +getFirstName() string
    }
    class Man {
        +accept(PersonVisitor*) void
    }
    class Woman {
        -vector~Person*~ children_
        +accept(PersonVisitor*) void
    }
    class PersonVisitor {
        +visit(Man*)* void
        +visit(Woman*)* void
    }
    class NamePrinter
    class MiddleNameVisitor
    Person <|-- Man
    Person <|-- Woman
    Woman o-- "0..*" Person : children
    PersonVisitor <|-- NamePrinter
    PersonVisitor <|-- MiddleNameVisitor
    Person ..> PersonVisitor : accept dispatches to
Loading

Command

Folder file: history.cpp

Intent. Wrap a request as an object, which lets you queue requests, log them, and support undo.

How this code does it. A Document is the receiver that inserts and removes lines. Command is the abstract request with execute and unexecute. InsertCommand and EraseCommand are concrete commands that know how to undo themselves. DocumentWithHistory is the invoker: it runs each command and pushes it on a stack, and undo pops the stack and calls unexecute. Storing commands as objects is what makes multi-level undo possible.

classDiagram
    class Document {
        +insert(int, string) void
        +remove(int) string
    }
    class Command {
        #Document* doc_
        +execute()* void
        +unexecute()* void
    }
    class InsertCommand
    class EraseCommand
    class DocumentWithHistory {
        -stack~Command*~ doneCommands_
        +insert(int, string) void
        +undo() void
    }
    Command <|-- InsertCommand
    Command <|-- EraseCommand
    Command o-- Document : acts on
    DocumentWithHistory o-- "0..*" Command : history stack
Loading

Memento

Folder file: snapshot.cpp

Intent. Capture an object's internal state so it can be restored later, without exposing the object's internals.

How this code does it. The Document is the originator. checkpoint returns a Memento that holds a copy of the whole document, and rollback copies that state back. The main is the caretaker: it keeps the memento and decides when to restore. The user edits text, takes a checkpoint, edits more, then rolls back to the saved state.

classDiagram
    class Document {
        -vector~string~ lines_
        +checkpoint() Memento*
        +rollback(Memento*) void
    }
    class Memento {
        -const Document doc_
        +getState() Document&
    }
    Document ..> Memento : creates and restores from
Loading

Prototype in the merged editor

Folder file: mergedFunctionality.cpp

This program (my own) stitches the editors together: a Document with a nested Memento, a command stack for undo, and checkpoint and rollback. It adds Prototype for redo. Command gains a clone method; redo clones a command from the history and runs the copy, so a past edit can be repeated without rebuilding it by hand. Prototype is the pattern of copying an existing object to make a new one.

Build and run

g++ -std=c++17 12-composite-command-memento/genealogy.cpp -o family
./family

g++ -std=c++17 12-composite-command-memento/mergedFunctionality.cpp -o editor
./editor

The editors read single-letter options from standard input as they run.

Notes

The genealogy framework and the three single-pattern editors came from the course. My work is the MiddleNameVisitor and the merged editor that brings Command, Memento, and Prototype together in one program with redo.

Clone this wiki locally