What design patterns are
Design patterns are time-tested, reusable solutions to commonly occurring problems within a given context in software design. They are not specific pieces of code. They are templates, or descriptions of how to solve a problem, that can be used in many different situations. Understanding and applying design patterns helps create more flexible, maintainable and understandable software.
Design patterns provide a shared vocabulary among developers, which makes it easier to talk about software design. They represent best practices that experienced developers have evolved over time.
At a glance
| Category | Pattern | Core intent or problem solved | Common C# use case or example |
|---|---|---|---|
| Creational | Singleton | Ensure a class has only one instance, and provide a global access point. | Logging service, configuration manager, database connection pool (conceptually). Lazy<T> for a thread-safe instance. |
| Creational | Factory Method | Define an interface for creating an object, but let subclasses decide which class to instantiate. | Creating different types of documents in an application, for example WordDocumentFactory and PdfDocumentFactory. |
| Creational | Abstract Factory | Provide an interface for creating families of related objects without specifying concrete classes. | UI toolkits supporting multiple themes, for example DarkThemeFactory and LightThemeFactory creating buttons and textboxes. |
| Structural | Decorator | Attach additional responsibilities to an object dynamically. | Adding compression or encryption to streams (CryptoStream wrapping FileStream). |
| Structural | Adapter | Convert the interface of a class into another interface clients expect. | Making a legacy logging component compatible with a new ILogger interface. |
| Structural | Facade | Provide a simplified interface to a complex subsystem. | A single OrderPlacementFacade simplifying interactions with the inventory, payment and notification services. |
| Behavioral | Strategy | Define a family of algorithms, encapsulate each, and make them interchangeable. | Different payment processing strategies, for example CreditCardPaymentStrategy and PayPalPaymentStrategy. |
| Behavioral | Observer | Define a one-to-many dependency so that when one object changes state, its dependents are notified. | UI event handling (button clicks), stock price updates notifying subscribers. The C# event keyword. |
| Architectural | Repository | Mediate between the domain and data mapping layers using a collection-like interface. | Abstracting data access logic, for example IProductRepository with methods like GetProductByIdAsync and AddProductAsync. |
Each category has its own note: creationalCreational patternsFour patterns for creating objects in a way that suits the situation.Opens in a new tab, structuralStructural patternsFour patterns for composing classes and objects into larger structures.Opens in a new tab and behavioralBehavioral patternsFour patterns for how objects interact and share out responsibilities.Opens in a new tab, plus the Repository patternRepository patternA collection-like interface over data access, and when it is worth adding.Opens in a new tab.
A word of caution
Design patterns are powerful tools, but how well they work depends on understanding the problem they solve and their inherent trade-offs. Blindly applying a pattern can lead to over-engineering. Choose patterns judiciously, focusing on solving the actual problem at hand rather than using a pattern for its own sake.
Sources
- Mastering C# Design Patterns: Practical Examples of Singleton, Factory, and Observer, DEV · accessed May 16, 2025
- Design Patterns in C#, Refactoring.Guru · accessed May 16, 2025
- The Repository Pattern in C#, CodeGuru · accessed May 16, 2025
- Gentle introduction to Generic Repository Pattern with C#, DEV · accessed May 16, 2025