Design Patterns Mastery

Observer Pattern: Pub/Sub & Event-driven architecture

2 Views Updated 5/6/2026

The Observer Pattern

The Observer Pattern defines a one-to-many dependency between objects. When one object (the Subject) changes state, all its dependents (the Observers) are notified and updated automatically. This is the heart of every modern UI framework and event-driven system.

1. Real-World .NET Example: events

In C#, we don't usually build Observe() and Notify() methods from scratch. We use the event keyword. This is the Observer pattern baked into the language.

public class StockTicker 
{
    // The SUBJECT
    public event Action<decimal> OnPriceChanged;

    public void UpdatePrice(decimal p) => OnPriceChanged?.Invoke(p);
}

// THE OBSERVERS
ticker.OnPriceChanged += (p) => Console.WriteLine($"UI updated: {p}");
ticker.OnPriceChanged += (p) => Logger.Log(p); 

2. Decoupling

The StockTicker has NO IDEA which classes are listening to it. You can add 50 new listeners (mobile app, email service, audit log) without changing a single line of logic in the ticker. This is the ultimate tool for handling "Secondary Effects."

4. Interview Mastery

Q: "What is the danger of the Observer pattern in C# if you forget to 'Unsubscribe'?"

Architect Answer: "Memory Leaks. When you write `ticker.OnPriceChanged += ObserverMethod;`, the Subject (ticker) now holds a strong reference to your observer class in its internal delegate list. As long as the ticker is alive, the Garbage Collector refuses to delete your observer, even if you are 'done' with it. This is a very common leak in WPF and long-running services. You MUST always use `-=` or implement `IDisposable` to clean up your subscriptions."

Design Patterns Mastery
1. Introduction to Design Patterns
Introduction to GoF Patterns: Why patterns matter? SOLID Principles: The foundation of all patterns DRY, KISS, and YAGNI (Architectural Philosophy)
2. Creational Patterns
Singleton Pattern: Thread-safety & Captive Dependencies Factory Method: Abstracting complex object creation Abstract Factory: Creating families of related objects Builder Pattern: Constructing complex fluents Prototype Pattern: Cloning high-cost objects
3. Structural Patterns
Adapter Pattern: Bridging incompatible interfaces Bridge Pattern: Decoupling abstraction from implementation Composite Pattern: Managing tree structures & hierarchies Decorator Pattern: Enhancing behavior without inheritance Facade Pattern: Simplifying complex library subsystems Flyweight Pattern: Drastically reducing memory footprint Proxy Pattern: Interception, Lazy-Loading, and Security
4. Behavioral Patterns
Chain of Responsibility: Middleware & Pipeline Architecture Command Pattern: Implementing Undo/Redo & Queueing Interpreter Pattern: Building domain-specific languages Iterator Pattern: Unified traversal of collections Mediator Pattern: Decoupling components with MediatR Memento Pattern: Capturing and restoring object state Observer Pattern: Pub/Sub & Event-driven architecture State Pattern: Managing complex object lifecycles Strategy Pattern: Swappable algorithms at runtime Template Method: Defining skeleton algorithms Visitor Pattern: Separating operations from data structures
5. Modern Enterprise & Cloud Patterns
Repository & Unit of Work (The EF Core Standard) CQRS Pattern (Command Query Responsibility Segregation) Circuit Breaker & Retry Patterns (Resilience with Polly) Dependency Injection Pattern (The Modern King)