Observer Design Pattern in Java: Building Event-Driven Systems Through Publish-Subscribe Communication

Description / Meta Description

Learn the Observer Design Pattern in Java with practical examples. Understand how Observer enables publish-subscribe communication, event-driven architectures, loose coupling, and real-time notifications. Discover real-world applications in Spring Events, Kafka consumers, stock market systems, and microservices.


Observer Design Pattern in Java: Building Event-Driven Systems Through Publish-Subscribe Communication

In the previous article, we explored the Strategy Pattern, which helps us dynamically select algorithms at runtime.

Strategy answers:

How do I choose behavior dynamically?

Observer answers a different question:

How do I notify multiple interested parties when something changes?

This pattern sits at the heart of:

  • Event-Driven Architectures
  • Kafka Consumers
  • Spring Events
  • Notification Systems
  • Real-Time Dashboards
  • Stock Market Applications
  • Reactive Systems

If you’ve ever implemented an event, listener, subscriber, or callback mechanism, you’ve already used Observer Pattern.


The Problem: Tight Coupling

Imagine an e-commerce application.

A customer places an order.

Business requirements state:

Create Order
     ↓
Send Email
     ↓
Send SMS
     ↓
Update Analytics
     ↓
Update Inventory
     ↓
Generate Invoice

A naive implementation might look like:

public class OrderService {

    public void placeOrder() {

        createOrder();

        emailService.send();

        smsService.send();

        analyticsService.update();

        invoiceService.generate();
    }
}

Looks fine initially.


Then new requirements arrive:

Push Notifications
WhatsApp Messages
Loyalty Points
CRM Updates
Fraud Detection
Audit Logging

Now OrderService becomes:

Massive
Tightly Coupled
Difficult To Maintain

Every new feature requires modifying existing code.

This violates:

Open/Closed Principle

What We Really Want

Instead of:

Order Service
      │
      ├── Email
      ├── SMS
      ├── Analytics
      ├── Invoice
      └── Audit

We want:

Order Created Event
         │
         ▼

Subscribers

Email Listener
SMS Listener
Analytics Listener
Invoice Listener
Audit Listener

The order service shouldn’t care who listens.

It should simply publish an event.

This is Observer Pattern.


What is Observer Pattern?

Observer is a Behavioral Design Pattern that:

Defines a one-to-many dependency so that when one object changes state, all dependent objects are automatically notified.

In simple terms:

Publisher
     │
     ▼
Many Subscribers

When something happens:

Publisher
    Emits Event

All subscribers receive notification.


Real Life Example

Think about YouTube.

YouTube Channel
       │
       ▼
Subscribers

When a new video is uploaded:

Channel
    ↓
Notification
    ↓
All Subscribers

The channel doesn’t know:

  • who is watching
  • where they live
  • what device they use

It simply broadcasts an event.

Observer works the same way.


Observer Architecture

           Subject
              │
      ┌───────┼────────┐
      │       │        │

 Observer Observer Observer

The Subject publishes updates.

Observers react.


Step 1: Create Observer Interface

public interface Observer {

    void update(
            String event);
}

All observers implement this contract.


Step 2: Create Concrete Observers

Email Observer

public class EmailObserver
        implements Observer {

    @Override
    public void update(
            String event) {

        System.out.println(
            "Email Sent: " + event);
    }
}

SMS Observer

public class SmsObserver
        implements Observer {

    @Override
    public void update(
            String event) {

        System.out.println(
            "SMS Sent: " + event);
    }
}

Analytics Observer

public class AnalyticsObserver
        implements Observer {

    @Override
    public void update(
            String event) {

        System.out.println(
            "Analytics Updated");
    }
}

Step 3: Create Subject

public class OrderPublisher {

    private List<Observer> observers =
            new ArrayList<>();

    public void subscribe(
            Observer observer) {

        observers.add(observer);
    }

    public void notifyObservers(
            String event) {

        for(Observer observer
                : observers) {

            observer.update(event);
        }
    }
}

Step 4: Client Usage

OrderPublisher publisher =
        new OrderPublisher();

publisher.subscribe(
        new EmailObserver());

publisher.subscribe(
        new SmsObserver());

publisher.subscribe(
        new AnalyticsObserver());

publisher.notifyObservers(
        "Order Created");

Output:

Email Sent: Order Created
SMS Sent: Order Created
Analytics Updated

One event.

Multiple reactions.


Why Observer Works

Without Observer:

Order Service
      │
      ├── Email
      ├── SMS
      ├── Analytics
      └── Invoice

High coupling.


With Observer:

Order Service
      │
      ▼

Order Event

      │
      ▼

Subscribers

Loose coupling.

Easy extensibility.


Enterprise Example: Payment Processing

Payment succeeds.

Event published:

Payment Successful

Subscribers:

Invoice Service
Notification Service
Audit Service
Rewards Service
Analytics Service

Each reacts independently.

No direct dependency exists between them.


Kafka as Observer Pattern

One of the most popular modern implementations.

Producer:

Order Created Event

Kafka Topic:

orders

Consumers:

Inventory Service
Billing Service
Shipping Service
Analytics Service

Architecture:

Producer
    │
    ▼
 Kafka Topic
    │
 ┌──┼──┬───┐

Inventory
Billing
Shipping
Analytics

Classic Observer Pattern at scale.


Spring Events Example

Spring provides built-in Observer support.

Publisher:

applicationEventPublisher
        .publishEvent(
            new OrderCreatedEvent());

Listener:

@EventListener
public void handle(
        OrderCreatedEvent event) {

}

Spring automatically manages subscriptions.


Stock Market Example

Stock price changes:

AAPL = $250

Observers:

Trading System
Mobile App
Dashboard
Alert Service

All receive updates immediately.

Observer is ideal for real-time systems.


Benefits of Observer Pattern

1. Loose Coupling

Publisher knows nothing about subscribers.


2. Easy Extensibility

Add new subscribers.

No publisher changes required.


3. Open/Closed Principle

Extend behavior without modifying existing code.


4. Event-Driven Architecture

Foundation of modern distributed systems.


5. Reusability

Observers can subscribe to multiple events.


Common Mistakes

Mistake 1: Too Many Events

Publishing events for everything can create complexity.

Use meaningful business events.


Mistake 2: Slow Subscribers

One slow observer can affect processing.

Modern systems often use:

Async Events
Kafka
Message Queues

to solve this.


Mistake 3: Circular Notifications

Observer A triggers Observer B.

Observer B triggers Observer A.

Infinite loops become possible.

Design carefully.


Observer vs Strategy

Common interview question.


Strategy

Purpose:

Choose Algorithm

Example:

Card Payment
UPI Payment
Wallet Payment

Observer

Purpose:

Notify Interested Parties

Example:

Order Created
     ↓
Email
SMS
Analytics

Observer vs Chain of Responsibility


Observer

One Event
Many Receivers

All subscribers receive notification.


Chain of Responsibility

One Request
Many Processors

Request travels through a pipeline.

Different intent.


When Should You Use Observer?

Use Observer when:

✔ Multiple systems react to the same event

✔ Loose coupling is important

✔ Event-driven architecture exists

✔ Real-time notifications are needed

✔ Publish-subscribe communication fits naturally

Examples:

  • Notifications
  • Kafka Consumers
  • Spring Events
  • Trading Systems
  • Monitoring Platforms
  • Dashboards

Avoid Observer when:

❌ Only one consumer exists

❌ Direct method calls are simpler

❌ Event volume introduces unnecessary complexity


Behavioral Patterns Covered So Far

PatternPurpose
StrategySelect algorithms dynamically
ObserverPublish-subscribe communication

Behavioral Pattern Cheat Sheet

Strategy
→ Choose Behavior

Observer
→ Broadcast Events

Final Thoughts

The Observer Pattern solves one of the most common architectural challenges:

How do we allow multiple systems to react to the same event without tightly coupling them together?

By introducing publishers and subscribers, Observer enables:

  • Event-driven systems
  • Real-time notifications
  • Scalable architectures
  • Loose coupling
  • Better maintainability

This is why Observer powers:

  • Spring Events
  • Kafka
  • RabbitMQ Consumers
  • Monitoring Systems
  • Notification Platforms
  • Reactive Applications

Whenever you see:

Something Happened
     ↓
Many Things Need To React

you’re looking at a perfect Observer Pattern use case.

In the next article, we’ll explore another highly practical Behavioral Pattern:

Command Design Pattern — Encapsulating Requests as Objects

You’ll learn how job schedulers, Spring Batch, Quartz, workflow engines, undo functionality, and task execution frameworks rely heavily on Command Pattern concepts.

Leave a Reply

Your email address will not be published. Required fields are marked *