Fundamentals 7 min read

Observer Design Pattern in Java: Concepts, UML, and Full Code Example

This article explains the Observer behavioral design pattern, describes its participants, illustrates a real‑world e‑commerce scenario, and provides complete Java code for the observer interface, subject interface, concrete subject, concrete observers, and a test client, concluding with the pattern’s benefits.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Observer Design Pattern in Java: Concepts, UML, and Full Code Example

The Observer pattern is a behavioral design pattern that defines a one‑to‑many dependency between objects so that when one object (the subject) changes state, all its dependents (observers) are automatically notified and updated.

Key participants include:

Subject (Observable) : maintains a list of observers and provides methods to register, remove, and notify them.

Observer : defines the update interface that subjects call.

ConcreteSubject : implements the subject interface, holds its own state, and triggers notifications on state changes.

ConcreteObserver : implements the observer interface and performs specific actions when notified.

A typical e‑commerce example: when an order is paid, both the logistics system and the purchasing system must be informed to start shipping and restocking respectively.

Observer interface (Java)

package com.sample.patterns.observer;

// Abstract observer
public interface Observer {
    // Method called when subject changes
    void update();
}

Subject interface (Order)

package com.sample.patterns.observer;

// Order interface, the observable
public interface Order {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObserver();
}

Concrete subject: CustomerOrder

package com.sample.patterns.observer;
import java.util.ArrayList;
import java.util.List;

// Concrete observable class
public class CustomerOrder implements Order {
    private List
list = new ArrayList<>();
    // Order state: 0 = unpaid, 1 = paid
    private int state = 0;

    public int getState() { return state; }
    public void setState(int state) { this.state = state; notifyObserver(); }

    @Override
    public void registerObserver(Observer observer) { list.add(observer); }

    @Override
    public void removeObserver(Observer observer) { list.remove(observer); }

    // Notify all observers
    @Override
    public void notifyObserver() {
        for (Observer observer : list) {
            observer.update();
        }
    }
}

Concrete observer: LogisticsObserver

package com.sample.patterns.observer;

// Observer: Logistics system
public class LogisticsObserver implements Observer {
    private int state;
    private CustomerOrder order;

    public LogisticsObserver(CustomerOrder order) {
        this.order = order;
        this.order.registerObserver(this);
    }

    @Override
    public void update() {
        this.state = order.getState();
        System.out.println("Observer state updated to: " + this.state);
        // If paid, start transport
        if (this.state == 1) {
            System.out.println("Begin to transport!");
        }
    }
}

Concrete observer: PurchaseObserver

package com.sample.patterns.observer;

// Observer: Purchasing system
public class PurchaseObserver implements Observer {
    private int state;
    private CustomerOrder order;

    public PurchaseObserver(CustomerOrder order) {
        this.order = order;
        this.order.registerObserver(this);
    }

    @Override
    public void update() {
        this.state = order.getState();
        System.out.println("Observer state updated to: " + this.state);
        // If paid, start purchase
        if (this.state == 1) {
            System.out.println("Begin to purchase!");
        }
    }
}

Test client

package com.sample.patterns.observer;

// Test client
public class Client {
    public static void main(String[] args) {
        CustomerOrder order = new CustomerOrder();
        LogisticsObserver logisticsObserver = new LogisticsObserver(order);
        PurchaseObserver purchaseObserver = new PurchaseObserver(order);

        // Change order state to paid
        order.setState(1);
    }
}

Running the client produces output showing both observers receiving the state change and executing their respective actions (transport and purchase). The Observer pattern thus achieves loose coupling between subjects and observers, making it ideal for scenarios where multiple components need to stay synchronized with a single source of truth.

design patternsJavasoftware architectureObserver Patternbehavioral pattern
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.