Design Pattern 03 – Observer

Md Sajjad Hosen Noyon

6 May, 2025

The Observer Design Pattern is a powerful pattern in object-oriented programming. It is a behavioral design pattern used to create one-to-many relations between objects so that when one object(subject) changes its state, all its dependents (observer) are notified and updated automatically. This pattern is widely used in scenarios where an object needs to broadcast changes to multiple dependent objects without them being tightly coupled. In this blog, we will grasp what is Observer design pattern, explore its components, and how it works.

Characteristic of Observer design pattern
  1. Decoupling: The subject (the entity being observed) does not need to know who its observers are or what they do. It only broadcasts its state changes, and the observers handle these updates accordingly. This loose coupling makes the system more flexible and scalable.
  2. One-to-Many Relationship: The pattern facilitates a one-to-many relationship between a subject and its observers. When the state of the subject changes, all attached observers are notified and can react in their way.
  3. Subject and Observer Interface: The Subject typically provides methods to add, remove, and notify observers. Observers implement a common interface that requires them to have an update() method, which gets called when the subject’s state changes.
  4. Automatic State Updates: When a subject’s state changes, it automatically notifies all its registered observers, typically through a method like notifyObservers(). The observers then pull the new state of the subject.
  5. Dynamic and Reusable: Observers can be added or removed at runtime, allowing dynamic changes to how the system behaves. This makes the pattern highly reusable across different contexts.
  6. Chain of Events: Changes in one object can lead to changes in others, triggering a cascade of notifications. This can create a reactive system where objects react automatically to changes in other objects.
Components of the Observer Design Pattern
  1. Subject: The subject maintains a list of observers and notifies them of state changes.
  2. Observer: The observer interface defines the contract for concrete observer classes.
  3. ConcreteSubject: A class that implements the subject interface and manages the observers.
  4. ConcreteObserver: A class that implements the observer interface and receives notifications.
Implementing Observer Design Pattern: Smart Home Automation System

In the below example, the subject is a HomeController, which monitors various home conditions like motion detection, temperature, or security breaches. Different devices such as lights, cameras, alarms, or thermostats act as observers that react to the updates in the home system.

Scenario
  • motion sensor detects movement in the living room.
  • If any movement is detected the smart light turns on, and the security camera starts recording.
Step 1: Observer Interface
				
					// Observer Interface
interface SmartDevice {
    void update(String condition);
}
				
			
Step 2: Create the ConcreteObserver class
				
					// Concrete Observer (Light)
class SmartLight implements SmartDevice {
    @Override
    public void update(String condition) {
        if (condition.equals("Motion Detected")) {
            System.out.println("Smart Light: Motion detected, turning on lights.");
        } else {
            System.out.println("Smart Light: No motion, lights off.");
        }
    }
}

// Concrete Observer (Security Camera)
class SecurityCamera implements SmartDevice {
    @Override
    public void update(String condition) {
        if (condition.equals("Motion Detected")) {
            System.out.println("Security Camera: Motion detected, starting recording.");
        } else {
            System.out.println("Security Camera: No motion, recording stopped.");
        }
    }
}
				
			
Step 3: Subject Interface
				
					// Subject Interface
interface HomeController {
    void addDevice(SmartDevice device);
    void removeDevice(SmartDevice device);
    void notifyDevices();
}
				
			
Step 4: ConcreteSubject class
				
					// Concrete Subject (Home Controller)
class HomeControlSystem implements HomeController {
    private List<SmartDevice> devices;
    private String homeCondition;

    public HomeControlSystem() {
        devices = new ArrayList<>();
    }

    public void setHomeCondition(String condition) {
        this.homeCondition = condition;
        notifyDevices();
    }

    @Override
    public void addDevice(SmartDevice device) {
        devices.add(device);
    }

    @Override
    public void removeDevice(SmartDevice device) {
        devices.remove(device);
    }

    @Override
    public void notifyDevices() {
        for (SmartDevice device : devices) {
            device.update(homeCondition);
        }
    }
}
				
			
Step 5: Make it Happen
				
					// Test Client Code
public class SmartHomeTest {
    public static void main(String[] args) {
        HomeControlSystem homeController = new HomeControlSystem();

        SmartLight livingRoomLight = new SmartLight();
        SecurityCamera livingRoomCamera = new SecurityCamera();

        homeController.addDevice(livingRoomLight);
        homeController.addDevice(livingRoomCamera);

        // Simulate a home condition change: Motion detected
        homeController.setHomeCondition("Motion Detected"); // Both devices react

        // Simulate no motion
        homeController.setHomeCondition("No Motion"); // Both devices react
    }
}
				
			
Explanation
  • HomeControlSystem: This is the subject that maintains the current condition of the home (e.g., “Motion Detected” or “No Motion”). It notifies all registered devices whenever the condition changes.
  • SmartLight and SecurityCamera: These are the concrete observers that react to changes in the home condition. When motion is detected, the light turns on, and the camera starts recording.
  • notifyDevices(): Whenever the home condition changes, this method is triggered, and all devices (observers) update accordingly.
Value of the Observer Design Pattern
  • Real-time Automation: Whenever motion is detected, multiple devices are triggered, ensuring the system responds automatically to events without tight coupling.
  • Scalability: More devices can be added to the system (e.g., smart locks, and alarms) without changing the core logic of the home controller.
  • Flexibility: Each device can independently decide how to react to home conditions, making the system extensible and dynamic.

This scenario showcases how The Observer Pattern can be used in IoT (Internet of Things) or smart home applications, where multiple devices respond to events like motion, temperature changes, or security breaches.

Thanks for reading. See you! 👋

Md Sajjad Hosen Noyon

6 May, 2025