Capital Suite

COMPLETE

OOP concepts taught in isolation don't stick — you need a domain where inheritance, commands, and serialization all arise naturally and necessarily.

Banking is that domain. Every pattern has an obvious real-world motivation: accounts differ by behavior (inheritance), transactions must be undoable (command), balances must persist (serialization), and internal state must be protected (encapsulation).

Key Decision
The Command pattern for transactions enables undo — not just a design exercise. Every debit and credit is an object that knows how to reverse itself. This is why Command exists.
Account (abstract) ├─→ SavingsAccount interestRate() = 4% └─→ CurrentAccount interestRate() = 1% interface Command ├─→ DepositCmd { execute(), undo() } └─→ WithdrawCmd { execute(), undo() } Bank ├─→ Map<id, Account> (encapsulated state) ├─→ Deque<Command> (undo history) ├─→ run(cmd) (execute + push) ├─→ undoLast() (pop + undo) └─→ save() / load() (ObjectOutputStream)

Crystallized why patterns exist — not as abstractions to memorize, but as solutions to recurring problems that appear naturally when you build something real. The undo stack alone justified the entire Command pattern.

Would replace Java serialization with JSON (Jackson) — ObjectOutputStream is fragile across versions and makes the persistence format opaque.