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.