Observer Pattern: Event-Driven Systems
Observer Pattern: Event-Driven Systems
The Observer Pattern is a behavioral design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object theyโre observing.
๐๏ธ The Problem
Imagine you are building a Stock Market Application. Multiple parts of your app (the UI, the logging system, and the alert system) need to know whenever a stock price changes. If you hardcode these dependencies into the Stock class, it becomes tightly coupled and hard to maintain.
๐ The .NET Implementation
In modern .NET, the Observer pattern is often implemented using Events or the IObservable<T>/IObserver<T> interfaces.
1. The Subject (Observable)
public class Stock
{
public string Symbol { get; }
private decimal _price;
// Use built-in EventHandler for simple notification
public event EventHandler<decimal> PriceChanged;
public Stock(string symbol, decimal price)
{
Symbol = symbol;
_price = price;
}
public void UpdatePrice(decimal newPrice)
{
_price = newPrice;
// Notify all subscribers
PriceChanged?.Invoke(this, _price);
}
}2. The Observers (Subscribers)
public class MobileAlertSystem
{
public void OnPriceChanged(object sender, decimal newPrice)
{
var stock = (Stock)sender;
Console.WriteLine($"[MOBILE ALERT]: {stock.Symbol} price moved to {newPrice:C}");
}
}
public class LoggerSystem
{
public void OnPriceChanged(object sender, decimal newPrice)
{
var stock = (Stock)sender;
Console.WriteLine($"[LOG]: {stock.Symbol} updated in database: {newPrice:C}");
}
}๐ ๏ธ Real-World Usage (Client)
var appleStock = new Stock("AAPL", 150.00m);
var mobileAlerts = new MobileAlertSystem();
var logger = new LoggerSystem();
// Subscribe observers
appleStock.PriceChanged += mobileAlerts.OnPriceChanged;
appleStock.PriceChanged += logger.OnPriceChanged;
// This will trigger both the alert and the log
appleStock.UpdatePrice(155.50m);๐ก Why use Observer?
- Decoupling: The
Stockclass doesnโt need to know who is listening to it. - Dynamic Subscriptions: You can add or remove observers at runtime.
- Reactive Programming: This is the foundation of libraries like Reactive Extensions (Rx.NET).