Here, we will see how to create Observer Design Pattern with example.
Observer Design Pattern
The Observer Design Pattern is a behavioral design pattern
where an object (called the subject) maintains a list of its
dependents (called observers) and notifies them of any state
changes, usually by calling one of their methods. This pattern is useful when
you need many objects to be updated in real-time with changes to a particular
object.
Example
In this example, we will create a weather station that monitors and broadcasts
weather data. Different displays (like a mobile app, a website widget, or a
physical weather station) will subscribe to this data and update themselves
automatically when the weather changes. We will explain in detail lator part of
the article with
code example.
Advantages of the Observer Pattern
-
Loose Coupling - The subject and the observers are
loosely coupled because the subject doesn't need to know details about the
observers. The subject only needs to know that the observers implement a
certain interface.
-
Dynamic Subscription - Observers can subscribe or
unsubscribe from notifications at any time, making the system more flexible.
-
Real-Time Updates - Observers receive updates as soon as
the subject's state changes, ensuring real-time synchronization between the
subject and observers.
-
Reusability and Extensibility - Observers can be reused
and extended independently without modifying the subject.
-
Scalability - The pattern allows adding multiple
observers easily, enabling scalability of notifications to different parts
of the system.
When to Use the Observer Pattern
-
Multiple Objects Need to be Informed - Use it when
several objects need to be notified of a change in another object. For
example, in GUI applications where a change in the model should
automatically update the views.
-
Decoupling of Subject and Observer - When you want to
maintain a loose coupling between the object whose state changes and the
objects that need to react to those changes.
-
Dynamic Relationships - When relationships between
objects need to change at runtime, with observers being able to subscribe
and unsubscribe dynamically.
-
Event Handling Systems - It is useful in event-driven
systems, where different modules need to respond to specific changes or
events.
Problems in a System without the Observer Pattern
-
Tight Coupling - Without the observer pattern, the
subject class would need to keep references to all dependent objects,
increasing coupling and making the system rigid.
-
Code Duplication - Without a well-defined mechanism like
the observer pattern, you may end up writing similar notification logic
across multiple places in your codebase.
-
Manual Update Handling - Without this pattern, you'd have
to manually ensure that all dependent objects are notified when the state of
the subject changes, which increases complexity and the likelihood of bugs.
-
Scalability Issues - If the number of dependent objects
increases, maintaining and notifying them without an observer pattern
becomes inefficient and prone to errors.
Example of the Observer Pattern
In this example, we’ll create a weather station that monitors and broadcasts
weather data. Different displays (like a mobile app, a website widget, or a
physical weather station) will subscribe to this data and update themselves
automatically when the weather changes.
Components of the Observer Pattern
- Subject (Observable): This is the object whose state is
being monitored (i.e., the weather station).
- Observers: These are the objects that subscribe to the
subject and are notified whenever the subject’s state changes (i.e., weather
displays).
- Observer Interface: Defines how observers should update
themselves when the subject changes.
- Subject Interface: Defines how to register, remove, and
notify observers.
Here’s a simple example in C# using a weather station system, where the
weather station is the subject, and different display screens
act as observers.
C# Code
using System;
using System.Collections.Generic;
// Observer Interface
public interface IObserver
{
void Update(float temperature, float humidity, float pressure);
}
// Subject Interface
public interface IWeatherStation
{
void RegisterObserver(IObserver observer);
void RemoveObserver(IObserver observer);
void NotifyObservers();
}
// Concrete Subject (WeatherStation)
public class WeatherStation : IWeatherStation
{
private List<IObserver> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherStation()
{
observers = new List<IObserver>();
}
public void RegisterObserver(IObserver observer)
{
observers.Add(observer); // Add observer to the list
}
public void RemoveObserver(IObserver observer)
{
observers.Remove(observer); // Remove observer from the list
}
public void NotifyObservers()
{
// Notify each observer about the new weather conditions
foreach (IObserver observer in observers)
{
observer.Update(temperature, humidity, pressure);
}
}
// Method to simulate new weather data coming in
public void SetMeasurements(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
NotifyObservers(); // Notify all observers about the data change
}
}
// Concrete Observer (WeatherDisplay)
public class WeatherDisplay : IObserver
{
private float temperature;
private float humidity;
private float pressure;
// Called by the subject when its state changes
public void Update(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
Display();
}
// A simple method to display the weather conditions
public void Display()
{
Console.WriteLine($"Current conditions: Temperature = {temperature}°C, Humidity = {humidity}%, Pressure = {pressure} Pa");
}
}
// Main Program
public class Program
{
public static void Main(string[] args)
{
// Create the subject (WeatherStation)
WeatherStation weatherStation = new WeatherStation();
// Create an observer (WeatherDisplay)
WeatherDisplay display = new WeatherDisplay();
// Register the display as an observer of the weather station
weatherStation.RegisterObserver(display);
// Simulate new weather data coming into the weather station
weatherStation.SetMeasurements(25.0f, 65.0f, 1013.0f); // 25°C, 65% humidity, 1013 Pa
weatherStation.SetMeasurements(30.0f, 70.0f, 1009.0f); // 30°C, 70% humidity, 1009 Pa
}
}
Above Code Explanation
- WeatherStation - The subject that holds the weather
data (temperature, humidity, pressure) and notifies observers when these
values change.
- WeatherDisplay - The observer that displays the weather
data when notified of changes.
- IObserver - The interface that ensures all observers
implement the Update method.
- IWeatherStation - The interface that defines how to
register, remove, and notify observers.
Output
Real-World Examples of the Observer Pattern
-
Notification Systems - Many applications use the
observer pattern for event notifications. For example, a social media app
sends a notification to all followers when someone they follow posts a new
update.
-
Stock Market Tickers - A stock market system where
multiple screens or apps (observers) are updated whenever stock prices
(subject) change.
-
Email and Messaging Systems - When a user sends a
message, all subscribers to that message or email thread receive a
notification.
-
MVC Pattern - The Observer pattern is commonly used in
the Model-View-Controller (MVC) architecture, where the
model acts as the subject, and views act as observers. When the model
changes, all the views are notified to update the display.
Application of Observer Design Pattern
-
Real-Time Systems - Systems that require real-time
updates, like financial systems (e.g., stock price updates) or weather
stations.
-
Event Handling - Used in GUI frameworks, such as in
button click listeners and data binding mechanisms.
-
Distributed Systems - The Observer pattern can be useful
in distributed systems where clients (observers) need to be notified of
changes on the server (subject).
-
Multimedia Applications - In multimedia software, if one
element (like a volume control) changes, it can notify all dependent
elements like equalizers or visualizers to adjust accordingly.
-
Logging Frameworks - Used in logging systems where
different components (observers) need to record various system events from a
subject.
Prev
Next