05 Dec 2023
Advanced
The Observer design pattern is a behavioral pattern where an object, known as the subject, maintains a list of dependents, known as observers, that are notified of any state changes, typically by calling one of their methods. In C#, the Observer pattern typically involves the following main components:
-
Subject:
- Maintains a list of observers.
- Provides methods to attach, detach, and notify observers.
- Defines the interface for adding, removing, and notifying observers.
public abstract class Subject { private List<IObserver> observers = new List<IObserver>(); 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(); } } } -
ConcreteSubject:
- Extends the
Subjectclass. - Maintains the state of interest.
- Notifies observers when the state changes.
public class ConcreteSubject : Subject { private string state; public string State { get { return state; } set { state = value; Notify(); // Notify observers when the state changes } } } - Extends the
-
Observer:
- Defines an interface for objects that should be notified of changes in the subject.
- Typically includes an
Updatemethod.
public interface IObserver { void Update(); } -
ConcreteObserver:
- Implements the
IObserverinterface. - Maintains a reference to the
Subject. - Stores the state that should stay synchronized with the subject.
- Implements the
Updatemethod to react to changes in the subject.
public class ConcreteObserver : IObserver { private ConcreteSubject subject; private string observerState; public ConcreteObserver(ConcreteSubject subject) { this.subject = subject; } public void Update() { observerState = subject.State; Console.WriteLine($"Observer updated with state: {observerState}"); } } - Implements the
-
Client:
- Creates instances of the subject and observers.
- Attaches observers to the subject.
class Client { static void Main() { ConcreteSubject subject = new ConcreteSubject(); ConcreteObserver observer1 = new ConcreteObserver(subject); ConcreteObserver observer2 = new ConcreteObserver(subject); subject.Attach(observer1); subject.Attach(observer2); subject.State = "New State"; // This triggers the observers to be notified } }
In this example:
Subjectdefines the common interface for managing observers and notifying them of changes.ConcreteSubjectis a concrete implementation of the subject that maintains a state and notifies observers when the state changes.IObserveris the interface for objects that should be notified of changes in the subject.ConcreteObserveris a concrete implementation of the observer that maintains a reference to the subject and updates its state when notified.- The
Clientcreates instances of the subject and observers, attaches observers to the subject, and triggers changes in the subject to observe the notifications.
The Observer pattern allows a one-to-many dependency relationship between objects so that when one object changes its state, all its dependents are notified and updated automatically. This promotes loose coupling between the subject and its observers.