Lesson Completion
Back to course

Behavioral Patterns Part 3: Memento, Visitor, Interpreter

Beginner
12 minutes4.5Java

1. The Hook (The "Byte-Sized" Intro)

  • In a Nutshell: Memento = save/restore object state (undo/redo, checkpoints), Visitor = add operations to object structure without modifying classes (tax calculator for employees), Interpreter = interpret language grammar (regex, SQL parser).
  • Benefits: State management (Memento), extensibility (Visitor), language parsing (Interpreter).
  • Use: Memento for undo functionality, Visitor for operations on complex structures, Interpreter for DSLs!

Memento = game save points (save progress, load later). Visitor = health inspector (visits restaurant, performs inspection without changing restaurant). Interpreter = language translator (parse sentence structure, interpret meaning)!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy

  • Memento: Photo snapshot (capture moment, restore later)
  • Visitor: Tourist guide (visits sites, performs actions)
  • Interpreter: Grammar checker (parse sentences)

3. Technical Mastery (The "Deep Dive")

java
// =========================================== // 1. MEMENTO PATTERN // =========================================== // Memento (state holder) class EditorMemento { private final String content; EditorMemento(String content) { this.content = content; } String getContent() { return content; } } // Originator class TextEditor { private String content = ""; void write(String text) { content += text; } String getContent() { return content; } // Save state EditorMemento save() { return new EditorMemento(content); } // Restore state void restore(EditorMemento memento) { content = memento.getContent(); } } // Caretaker class History { private Stack<EditorMemento> history = new Stack<>(); void push(EditorMemento memento) { history.push(memento); } EditorMemento pop() { return history.isEmpty() ? null : history.pop(); } } // Usage: TextEditor editor = new TextEditor(); History history = new History(); editor.write("Hello "); history.push(editor.save() ); // Save state editor.write("World"); System.out.println(editor.getContent()); // Hello World editor.restore(history.pop()); // Undo! System.out.println(editor.getContent()); // Hello // =========================================== // 2. VISITOR PATTERN // =========================================== // Element interface interface Employee { void accept(Visitor visitor); } // Concrete elements class Manager implements Employee { private String name; private double salary; Manager(String name, double salary) { this.name = name; this.salary = salary; } public void accept(Visitor visitor) { visitor.visit(this); } String getName() { return name; } double getSalary() { return salary; } } class Developer implements Employee { private String name; private double salary; Developer(String name, double salary) { this.name = name; this.salary = salary; } public void accept(Visitor visitor) { visitor.visit(this); } String getName() { return name; } double getSalary() { return salary; } } // Visitor interface interface Visitor { void visit(Manager manager); void visit(Developer developer); } // Concrete visitor class SalaryCalculator implements Visitor { private double totalSalary = 0; public void visit(Manager manager) { double bonus = manager.getSalary() * 0.2; // 20% bonus totalSalary += manager.getSalary() + bonus; } public void visit(Developer developer) { double bonus = developer.getSalary() * 0.1; // 10% bonus totalSalary += developer.getSalary() + bonus; } double getTotalSalary() { return totalSalary; } } // Usage: List<Employee> employees = List.of( new Manager("Alice", 10000), new Developer("Bob", 8000) ); SalaryCalculator calculator = new SalaryCalculator(); for (Employee emp : employees) { emp.accept(calculator); } System.out.println("Total: $" + calculator.getTotalSalary()); // =========================================== // 3. INTERPRETER PATTERN // =========================================== // Expression interface interface Expression { boolean interpret(String context); } // Terminal expression class TerminalExpression implements Expression { private String data; TerminalExpression(String data) { this.data = data; } public boolean interpret(String context) { return context.contains(data); } } // Non-terminal expressions class OrExpression implements Expression { private Expression expr1; private Expression expr2; OrExpression(Expression expr1, Expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } public boolean interpret(String context) { return expr1.interpret(context) || expr2.interpret(context); } } class AndExpression implements Expression { private Expression expr1; private Expression expr2; AndExpression(Expression expr1, Expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } public boolean interpret(String context) { return expr1.interpret(context) && expr2.interpret(context); } } // Usage (interpret rule: "Alice OR Bob") Expression alice = new TerminalExpression("Alice"); Expression bob = new TerminalExpression("Bob"); Expression rule = new OrExpression(alice, bob); System.out.println(rule.interpret("Alice is here")); // true System.out.println(rule.interpret("Bob is here")); // true System.out.println(rule.interpret("Carol is here")); // false

5. The Comparison & Decision Layer

PatternUse When
MementoSave/restore state (undo/redo, checkpoints)
VisitorAdd operations to structure without modifying classes
InterpreterParse DSL, implement grammar

6. The "Interview Corner" (The Edge)

The "Killer" Interview Question: "Why use Visitor pattern?" Answer: Add operations without modifying classes (Open/Closed Principle)!

java
// Without Visitor: Need to modify each class class Employee { void calculateSalary() { /* ... */ } void calculateTax() { /* ... */ } // Add new operation = modify class! } // With Visitor: Add operation without modifying Employee class TaxCalculator implements Visitor { void visit(Manager m) { /* tax logic */ } void visit(Developer d) { /* tax logic */ } } // No need to modify Manager or Developer!

Pro-Tip: Memento for game saves:

java
// Game state class GameState { int level, lives, score; Memento save() { return new Memento(level, lives, score); } void load(Memento m) { this.level = m.level; this.lives = m.lives; this.score = m.score; } } // Save game Memento checkpoint = game.save(); // Player dies... game.load(checkpoint); // Restore from save!

Topics Covered

Java Fundamentals

Tags

#java#programming#beginner-friendly

Last Updated

2025-02-01