Strategy Pattern
Java Strategy Pattern (BEHAVIORAL PATTERN)
Dynamic behavior selection - like choosing payment method at checkout!
Strategy Pattern:
2. Real-World Analogy
Section titled “2. Real-World Analogy”YouTube Channel:
- Channel (Subject) uploads new video
- Subscribers (Observers) get notified automatically
- Subscribers can subscribe/unsubscribe anytime
3. Simple Example: Without vs With Observer
Section titled “3. Simple Example: Without vs With Observer”❌ Without Observer (Tight Coupling)
Section titled “❌ Without Observer (Tight Coupling)”class NewsAgency { private String news;
// Direct references to subscribers - BAD! private CNN cnn; private BBC bbc;
public void setNews(String news) { this.news = news; // Manually notify each subscriber cnn.update(news); // ❌ Tight coupling! bbc.update(news); // ❌ Hard to add new subscribers }}✅ With Observer (Loose Coupling)
Section titled “✅ With Observer (Loose Coupling)”// Step 1: Observer Interfaceinterface Subscriber { void update(String news);}
// Step 2: Subject Interfaceinterface NewsChannel { void subscribe(Subscriber subscriber); void unsubscribe(Subscriber subscriber); void notifySubscribers();}
// Step 3: Concrete Subjectclass YouTubeChannel implements NewsChannel { private List<Subscriber> subscribers = new ArrayList<>(); private String latestVideo;
public void uploadVideo(String videoTitle) { this.latestVideo = videoTitle; notifySubscribers(); // Auto-notify all! }
public void subscribe(Subscriber subscriber) { subscribers.add(subscriber); }
public void unsubscribe(Subscriber subscriber) { subscribers.remove(subscriber); }
public void notifySubscribers() { for (Subscriber subscriber : subscribers) { subscriber.update(latestVideo); } }}
// Step 4: Concrete Observersclass User implements Subscriber { private String name;
public User(String name) { this.name = name; }
public void update(String videoTitle) { System.out.println(name + " notified: New video - " + videoTitle); }}
// Usagepublic class Main { public static void main(String[] args) { YouTubeChannel channel = new YouTubeChannel();
User alice = new User("Alice"); User bob = new User("Bob"); User charlie = new User("Charlie");
// Subscribe channel.subscribe(alice); channel.subscribe(bob);
// Upload video - subscribers auto-notified channel.uploadVideo("Java Tutorial"); // Output: // Alice notified: New video - Java Tutorial // Bob notified: New video - Java Tutorial
// Unsubscribe and upload channel.unsubscribe(bob); channel.subscribe(charlie);
channel.uploadVideo("Spring Boot Guide"); // Output: // Alice notified: New video - Spring Boot Guide // Charlie notified: New video - Spring Boot Guide }}4. Java’s Built-in Observer (Deprecated but Good to Know)
Section titled “4. Java’s Built-in Observer (Deprecated but Good to Know)”import java.util.Observable;import java.util.Observer;
// Subject (extends Observable)class WeatherStation extends Observable { private int temperature;
public void setTemperature(int temp) { this.temperature = temp; setChanged(); // Mark as changed notifyObservers(temp); // Notify observers }}
// Observer (implements Observer)class PhoneDisplay implements Observer { public void update(Observable o, Object arg) { System.out.println("Phone: Temperature is " + arg + "°C"); }}
// UsageWeatherStation station = new WeatherStation();station.addObserver(new PhoneDisplay());station.setTemperature(25); // Auto-notifies5. Real-World Examples
Section titled “5. Real-World Examples”Example 1: Stock Market
Section titled “Example 1: Stock Market”interface StockObserver { void update(String stock, double price);}
class StockMarket { private Map<String, Double> stocks = new HashMap<>(); private List<StockObserver> observers = new ArrayList<>();
public void setPrice(String stock, double price) { stocks.put(stock, price); notifyObservers(stock, price); }
public void addObserver(StockObserver observer) { observers.add(observer); }
private void notifyObservers(String stock, double price) { for (StockObserver observer : observers) { observer.update(stock, price); } }}
class Trader implements StockObserver { private String name;
public Trader(String name) { this.name = name; }
public void update(String stock, double price) { if (price > 100) { System.out.println(name + ": Selling " + stock + " at $" + price); } }}Example 2: Event Manager in GUI
Section titled “Example 2: Event Manager in GUI”// Button click listeners are observers!class Button { private List<ClickListener> listeners = new ArrayList<>();
public void addClickListener(ClickListener listener) { listeners.add(listener); }
public void click() { System.out.println("Button clicked!"); for (ClickListener listener : listeners) { listener.onClick(); } }}
interface ClickListener { void onClick();}
class SaveButtonListener implements ClickListener { public void onClick() { System.out.println("Saving document..."); }}6. Spring Framework Example
Section titled “6. Spring Framework Example”// Spring's ApplicationEvent and ApplicationListener@Componentclass OrderPlacedEvent extends ApplicationEvent { private String orderId;
public OrderPlacedEvent(Object source, String orderId) { super(source); this.orderId = orderId; }}
@Componentclass EmailService implements ApplicationListener<OrderPlacedEvent> { @Override public void onApplicationEvent(OrderPlacedEvent event) { System.out.println("Sending email for order: " + event.getOrderId()); }}
@Componentclass InventoryService implements ApplicationListener<OrderPlacedEvent> { @Override public void onApplicationEvent(OrderPlacedEvent event) { System.out.println("Updating inventory for order: " + event.getOrderId()); }}
// Publisher@Serviceclass OrderService { @Autowired private ApplicationEventPublisher eventPublisher;
public void placeOrder(String orderId) { // Process order... eventPublisher.publishEvent(new OrderPlacedEvent(this, orderId)); }}7. Interview Q&A
Section titled “7. Interview Q&A”Q1: Observer vs Pub-Sub?
Section titled “Q1: Observer vs Pub-Sub?”A:
- Observer: Direct relationship (subject knows observers)
- Pub-Sub: Indirect via message broker (decoupled)
Q2: Push vs Pull Model?
Section titled “Q2: Push vs Pull Model?”A:
- Push: Subject sends all data to observers
- Pull: Observers fetch data from subject when notified
// Push model (shown above) - subject sends datavoid update(String data);
// Pull model - observer fetches datavoid update(); // Observer calls subject.getData()Q3: Real examples in Java?
Section titled “Q3: Real examples in Java?”A:
java.util.Observer/Observable(deprecated)PropertyChangeListenerin SwingEvent Listenersin AWT/SwingApplicationListenerin SpringReactive Streams(RxJava, Reactor)
Q4: Advantages?
Section titled “Q4: Advantages?”A:
- Loose coupling - Subject doesn’t know observer details
- Dynamic relationships - Can add/remove observers at runtime
- Broadcast communication - One change notifies many
- Open/Closed - Easy to add new observers
Q5: Disadvantages?
Section titled “Q5: Disadvantages?”A:
- Memory leaks - Forgot to unsubscribe
- Unexpected updates - Cascading notifications
- Performance - Many observers can be slow
- Debugging hard - Chain of notifications
Q6: How to prevent memory leaks?
Section titled “Q6: How to prevent memory leaks?”A: Use WeakReference or ensure unsubscribe:
// Method 1: Auto-unsubscribetry { subject.subscribe(observer); // Do work} finally { subject.unsubscribe(observer);}
// Method 2: WeakReferenceprivate List<WeakReference<Observer>> observers = new ArrayList<>();8. Modern Implementation with Java 8+
Section titled “8. Modern Implementation with Java 8+”// Using Functional Interfacesclass EventBus { private List<Consumer<String>> handlers = new ArrayList<>();
public void subscribe(Consumer<String> handler) { handlers.add(handler); }
public void publish(String event) { handlers.forEach(handler -> handler.accept(event)); }}
// Usage with lambdasEventBus bus = new EventBus();bus.subscribe(event -> System.out.println("Handler 1: " + event));bus.subscribe(event -> System.out.println("Handler 2: " + event));bus.publish("Event occurred!");9. Implementation Template
Section titled “9. Implementation Template”// 1. Observer Interfaceinterface Observer { void update(Object data);}
// 2. Subject Interfaceinterface Subject { void attach(Observer observer); void detach(Observer observer); void notifyObservers();}
// 3. Concrete Subjectclass ConcreteSubject implements Subject { private List<Observer> observers = new ArrayList<>(); private Object state;
public void setState(Object state) { this.state = state; notifyObservers(); }
public void attach(Observer observer) { observers.add(observer); }
public void detach(Observer observer) { observers.remove(observer); }
public void notifyObservers() { for (Observer observer : observers) { observer.update(state); } }}
// 4. Concrete Observerclass ConcreteObserver implements Observer { public void update(Object data) { System.out.println("Received: " + data); }}