Lesson Completion
Back to course

Behavioral Patterns Part 1: Observer, Strategy, Command, Template Method

Beginner
12 minutes4.7Java

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

  • In a Nutshell: Behavioral patterns define object communication. Observer = one-to-many notification (YouTube subscribers), Strategy = encapsulate algorithms, switch at runtime (payment methods), Command = encapsulate request as object (undo/redo), Template Method = algorithm skeleton, subclasses fill steps (recipe framework).
  • Benefits: Loose coupling, flexibility, extensibility.
  • Use: Observer for event systems, Strategy for interchangeable algorithms, Command for queuing/undo, Template Method for algorithm frameworks!

Observer = news subscription (1 publisher, many subscribers). Strategy = navigation (walk/drive/fly, choose at runtime). Command = restaurant order (waiter → kitchen). Template Method = cooking recipe (heat→add ingredients→serve, specifics vary)!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy

  • Observer: Newsletter (one sender, many receivers)
  • Strategy: Payment methods (credit card, PayPal, cash)
  • Command: TV remote button (button → action)
  • Template Method: Assembly line (steps fixed, details vary)

3. Technical Mastery (The "Deep Dive")

java
// =========================================== // 1. OBSERVER PATTERN // =========================================== // Observer interface interface Observer { void update(String message); } // Subject (Observable) class NewsAgency { private List<Observer> observers = new ArrayList<>(); private String news; void addObserver(Observer observer) { observers.add(observer); } void removeObserver(Observer observer) { observers.remove(observer); } void setNews(String news) { this.news = news; notifyObservers(); } private void notifyObservers() { for (Observer observer : observers) { observer.update(news); } } } // Concrete observers class EmailSubscriber implements Observer { private String email; EmailSubscriber(String email) { this.email = email; } public void update(String message) { System.out.println("Email to " + email + ": " + message); } } // Usage: NewsAgency agency = new NewsAgency(); agency.addObserver(new EmailSubscriber("alice@example.com")); agency.addObserver(new EmailSubscriber("bob@example.com")); agency.setNews("Breaking news!"); // Notifies all subscribers // =========================================== // 2. STRATEGY PATTERN // =========================================== // Strategy interface interface PaymentStrategy { void pay(int amount); } // Concrete strategies class CreditCardPayment implements PaymentStrategy { public void pay(int amount) { System.out.println("Paid $" + amount + " with credit card"); } } class PayPalPayment implements PaymentStrategy { public void pay(int amount) { System.out.println("Paid $" + amount + " with PayPal"); } } class CashPayment implements PaymentStrategy { public void pay(int amount) { System.out.println("Paid $" + amount + " with cash"); } } // Context class ShoppingCart { private PaymentStrategy paymentStrategy; void setPaymentStrategy(PaymentStrategy strategy) { this.paymentStrategy = strategy; } void checkout(int amount) { paymentStrategy.pay(amount); } } // Usage: ShoppingCart cart = new ShoppingCart(); cart.setPaymentStrategy(new CreditCardPayment()); cart.checkout(100); cart.setPaymentStrategy(new PayPalPayment()); // Switch strategy! cart.checkout(50); // =========================================== // 3. COMMAND PATTERN // =========================================== // Command interface interface Command { void execute(); void undo(); } // Receiver class Light { void turnOn() { System.out.println("Light ON"); } void turnOff() { System.out.println("Light OFF"); } } // Concrete commands class LightOnCommand implements Command { private Light light; LightOnCommand(Light light) { this.light = light; } public void execute() { light.turnOn(); } public void undo() { light.turnOff(); } } class LightOffCommand implements Command { private Light light; LightOffCommand(Light light) { this.light = light; } public void execute() { light.turnOff(); } public void undo() { light.turnOn(); } } // Invoker class RemoteControl { private Command command; private Stack<Command> history = new Stack<>(); void setCommand(Command command) { this.command = command; } void pressButton() { command.execute(); history.push(command); } void pressUndo() { if (!history.isEmpty()) { Command lastCommand = history.pop(); lastCommand.undo(); } } } // Usage: Light light = new Light(); RemoteControl remote = new RemoteControl(); remote.setCommand(new LightOnCommand(light)); remote.pressButton(); // Light ON remote.pressUndo(); // Light OFF (undo!) // =========================================== // 4. TEMPLATE METHOD PATTERN // =========================================== // Abstract class with template method abstract class DataProcessor { // Template method (final = can't override) final void process() { loadData(); processData(); saveData(); } // Steps (some abstract, some with default implementation) abstract void loadData(); abstract void processData(); void saveData() { System.out.println("Data saved"); // Default implementation } } // Concrete classes class CSVProcessor extends DataProcessor { void loadData() { System.out.println("Loading CSV"); } void processData() { System.out.println("Processing CSV"); } } class XMLProcessor extends DataProcessor { void loadData() { System.out.println("Loading XML"); } void processData() { System.out.println("Processing XML"); } @Override void saveData() { System.out.println("Saving XML (custom)"); } } // Usage: DataProcessor csv = new CSVProcessor(); csv.process(); // Calls template method DataProcessor xml = new XMLProcessor(); xml.process();

5. The Comparison & Decision Layer

PatternUse When
ObserverOne-to-many notifications (event systems, MVC)
StrategyInterchangeable algorithms (sorting, compression)
CommandEncapsulate requests (undo/redo, queueing)
Template MethodAlgorithm skeleton with varying steps (frameworks)

6. The "Interview Corner" (The Edge)

The "Killer" Interview Question: "Strategy vs Template Method?" Answer:

  • Strategy: Composition-based, choose algorithm at runtime
  • Template Method: Inheritance-based, subclass provides implementation
java
// Strategy: Runtime selection cart.setPaymentStrategy(new PayPalPayment()); // Can change! // Template Method: Compile-time selection DataProcessor processor = new CSVProcessor(); // Fixed at creation

Pro-Tip: Observer in Java:

java
// Built-in Observer (deprecated, but concept remains) // Modern: Use PropertyChangeListener, EventListener // JavaFX uses Observer for properties StringProperty name = new SimpleStringProperty(); name.addListener((obs, oldVal, newVal) -> { System.out.println("Changed: " + oldVal + " → " + newVal); }); name.set("Alice"); // Notifies listener!

Topics Covered

Java Fundamentals

Tags

#java#programming#beginner-friendly

Last Updated

2025-02-01