skip to content
Mohammad Rebati

Understanding the Observer Design Pattern

/ 2 min read

Introduction to the Observer Design Pattern

The Observer Design Pattern is a behavioral design pattern that allows an object, known as the subject, to notify other objects, known as observers, about changes in its state. This pattern is particularly useful in scenarios where a change to one object requires changing others, and where an object needs to notify an open-ended number of other objects.

Key Concepts

  • Subject: The object that holds the state. It provides methods to attach and detach observers to a client object.
  • Observer: An interface or abstract class with a method update() that is called when the Subject changes.
  • Concrete Observer: Implements the Observer interface and performs some actions when it is notified of a change in the Subject.
  • Concrete Subject: A subclass of Subject that maintains a collection of observers and notifies them of state changes.

Benefits

  • Decoupling: The subject and observers are loosely coupled. The subject knows nothing about the observers other than that they implement the Observer interface.
  • Dynamic Relationships: New observers can be added or removed at runtime if the application’s requirement changes.
  • Broadcast Communication: Changes in the subject can be broadcast to all interested and registered observers without knowing their specific details.

Example in Code

Here’s how you might implement the Observer Pattern in C# to handle a scenario where an item’s price change needs to be communicated to multiple clients:

// Observer interface
public interface IObserver
{
void Update(ISubject subject);
}
// Concrete observer
public class ConcreteObserver : IObserver
{
public void Update(ISubject subject)
{
if (subject is ConcreteSubject concreteSubject)
{
Console.WriteLine("Received update! New state: " + concreteSubject.State);
}
}
}
// Subject interface
public interface ISubject
{
void Attach(IObserver observer);
void Detach(IObserver observer);
void Notify();
}
// Concrete subject
public class ConcreteSubject : ISubject
{
private List<IObserver> _observers = new List<IObserver>();
public int State { get; set; }
public void Attach(IObserver observer)
{
_observers.Add(observer);
}
public void Detach(IObserver observer)
{
_observers.Remove(observer);
}
public void Notify()
{
foreach (var observer in _observers)
{
observer.Update(this);
}
}
}
// Example usage
class Program
{
static void Main(string[] args)
{
var subject = new ConcreteSubject();
var observer1 = new ConcreteObserver();
var observer2 = new ConcreteObserver();
subject.Attach(observer1);
subject.Attach(observer2);
subject.State = 123;
subject.Notify();
subject.Detach(observer1);
subject.State = 456;
subject.Notify();
}
}