Stay in Sync with the Observer Pattern

Keep objects updated without tight coupling

Posted by Hüseyin Sekmenoğlu on July 08, 2021 Design Patterns

🧐 What Is the Observer Pattern?

The Observer Pattern is a behavioural design pattern that defines a one-to-many relationship between objects. When the subject changes its state, all its observers are automatically notified and updated.

It is like a news subscription service. When new content is published, everyone subscribed to that topic gets notified instantly.


🕵️ When to Use It

Use the Observer Pattern when:

  • An object must notify other objects without knowing who they are

  • You want to build a publish-subscribe system

  • You need to decouple objects that change from the objects that react to changes

Common examples include:

  • UI frameworks updating components when state changes

  • Event handling systems

  • Notification systems in messaging apps

  • Data-binding in reactive applications


🛠️ How It Works

The pattern consists of:

  1. A Subject that maintains a list of observers and notifies them

  2. One or more Observers that subscribe to the subject and act on updates

C# Example: Weather Monitoring

// Observer Interface
public interface IWeatherObserver
{
    void Update(float temperature);
}

// Concrete Observer
public class PhoneDisplay : IWeatherObserver
{
    public void Update(float temperature)
    {
        Console.WriteLine($"Phone: Current temperature is {temperature}°C");
    }
}

// Another Observer
public class WebDashboard : IWeatherObserver
{
    public void Update(float temperature)
    {
        Console.WriteLine($"Web: Updated dashboard with {temperature}°C");
    }
}

// Subject
public class WeatherStation
{
    private List<IWeatherObserver> _observers = new();
    private float _temperature;

    public void Subscribe(IWeatherObserver observer)
    {
        _observers.Add(observer);
    }

    public void Unsubscribe(IWeatherObserver observer)
    {
        _observers.Remove(observer);
    }

    public void SetTemperature(float temperature)
    {
        _temperature = temperature;
        NotifyObservers();
    }

    private void NotifyObservers()
    {
        foreach (var observer in _observers)
        {
            observer.Update(_temperature);
        }
    }
}

Usage

var station = new WeatherStation();
var phone = new PhoneDisplay();
var web = new WebDashboard();

station.Subscribe(phone);
station.Subscribe(web);

station.SetTemperature(25.5f);
station.SetTemperature(27.3f);

✅ Advantages

  • Promotes loose coupling between objects

  • Makes the system more flexible and extensible

  • Encourages event-driven design

  • Simplifies state broadcasting


❌ Disadvantages

  • Observers can become outdated if not managed properly

  • Harder to debug due to indirect communication

  • Risk of memory leaks if observers are not removed


🧪 Testing Benefits

  • You can mock observers to verify notifications

  • Easy to simulate state changes and observe reactions

  • Subject and observer can be tested independently


🌍 Real-World Use Cases

  • UI frameworks: Reactivity and data binding

  • Stock market apps: Notify users when prices change

  • Social media: Follow and unfollow notification systems

  • Build tools: Watchers that recompile when files change


🔗 Related Patterns

  • Mediator: Centralizes communication between objects rather than letting them talk directly

  • Event Bus: A more global version of publish-subscribe

  • Command: Used when actions must be queued or stored rather than broadcast


🎯 Final Thoughts

The Observer Pattern is ideal when multiple parts of your system need to react to changes in real time. It makes your codebase more modular and event-driven while keeping responsibilities clearly separated.