Design Patterns Mastery

Decorator Pattern: Enhancing behavior without inheritance

1 Views Updated 5/4/2026

The Decorator Pattern

The Decorator Pattern allows you to "Wrap" an object to add new functionality at runtime, without modifying the original class. This is far more flexible than inheritance because you can stack multiple decorators on top of each other like Russian nesting dolls.

1. Scenario: Encrypted Data Storage

You have a FileStore. You want to add Logging and Encryption. If you use inheritance, you need: LoggedFileStore, EncryptedFileStore, and LoggedEncryptedFileStore. With Decorators, you just wrap them.

// The core object
var store = new SimpleFileStore();

// Wrap it in a Logger!
var loggedStore = new LoggingDecorator(store);

// Wrap THAT in an Encryptor!
var secureStore = new EncryptionDecorator(loggedStore);

// When you call .Save(), it runs Encryption -> Logging -> Simple Saving.
secureStore.Save("data.txt");

2. Real-World .NET Example: Streams

The System.IO namespace is filled with decorators. FileStream is the base. BufferedStream decorates it with a buffer. CryptoStream decorates it with encryption. You can pipe them together seamlessly!

4. Interview Mastery

Q: "How does the Decorator pattern relate to the Open/Closed Principle?"

Architect Answer: "It is the perfect manifestation of OCP. We want to add new behavior (e.g., Auditing) to an existing service. Instead of opening the existing service code and potentially breaking it, we keep it 'Closed' for modification. We 'Open' the system for extension by creating a separate Decorator class that wraps the original. The original code remains pure and untouched, while the application gains new capabilities."

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)