🔔 Observer Design Pattern
The Observer Pattern is a behavioral design pattern where:
-
An object (subject) maintains a list of dependents (observers).
-
When the subject’s state changes, it notifies all observers automatically.
Think of it as a subscription system:
-
Subject = publisher (e.g., a puzzle or a timer in the escape room).
-
Observers = subscribers (e.g., doors, traps, or players listening for changes).
Escape Room Example Scenario
Section titled “Escape Room Example Scenario”In an escape room:
-
Solving a puzzle (subject) might trigger multiple reactions:
-
A door opens.
-
A light turns on.
-
A trap is disabled.
-
Define the Observer Interface
Section titled “Define the Observer Interface”// Observer interfacepublic interface Observer { void update(String event);}Define the Subject Interface
Section titled “Define the Subject Interface”// Subject interfacepublic interface Subject { void addObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(String event);}Implement a Concrete Subject
Section titled “Implement a Concrete Subject”import java.util.ArrayList;import java.util.List;
public class Puzzle implements Subject { private List<Observer> observers = new ArrayList<>(); private boolean solved = false;
@Override public void addObserver(Observer observer) { observers.add(observer); }
@Override public void removeObserver(Observer observer) { observers.remove(observer); }
@Override public void notifyObservers(String event) { for (Observer observer : observers) { observer.update(event); } }
public void solvePuzzle() { solved = true; System.out.println("Puzzle solved!"); notifyObservers("Puzzle solved"); }
public boolean isSolved() { return solved; }}Implement Concrete Observers
Section titled “Implement Concrete Observers”import java.util.ArrayList;import java.util.List;
public class Puzzle implements Subject { private List<Observer> observers = new ArrayList<>(); private boolean solved = false;
@Override public void addObserver(Observer observer) { observers.add(observer); }
@Override public void removeObserver(Observer observer) { observers.remove(observer); }
@Override public void notifyObservers(String event) { for (Observer observer : observers) { observer.update(event); } }
public void solvePuzzle() { solved = true; System.out.println("Puzzle solved!"); notifyObservers("Puzzle solved"); }
public boolean isSolved() { return solved; }}Using the Observer in the Game
Section titled “Using the Observer in the Game”public class EscapeRoomGame { public static void main(String[] args) { Puzzle puzzle = new Puzzle();
// Create observers Door door = new Door(); Light light = new Light(); Trap trap = new Trap();
// Subscribe them to puzzle events puzzle.addObserver(door); puzzle.addObserver(light); puzzle.addObserver(trap);
// Solve puzzle puzzle.solvePuzzle(); // Output: // Puzzle solved! // The door creaks open... // The lights flicker on! // The trap mechanism is disabled. }}Why is this Useful in a Game?
Section titled “Why is this Useful in a Game?”-
Loose coupling: Puzzle doesn’t need to know what happens after solving — it just notifies.
-
Flexibility: You can add/remove observers at runtime.
-
Reusability: Same observer (e.g.,
Light) could listen to different subjects (multiple puzzles).
Next Step Ideas 💡
Section titled “Next Step Ideas 💡”-
Add a Timer subject that notifies observers (e.g., “Time’s up!” → lock doors).
-
Allow players to be observers (notified when something changes).
-
Combine with Strategy Pattern so puzzles have different solving strategies and can notify observers when solved.
✅ Key Takeaway:
The Observer Pattern makes your game reactive. Solving one puzzle can ripple through the room, triggering doors, lights, or traps without hardcoding dependencies.