A design pattern is a named solution to a problem that keeps coming back in object-oriented code. There is nothing to install. You apply its shape to your own classes, and in C# most of the classic patterns come down to an interface and a handful of small types.
There are a lot of different design patterns in C#, and you can find a pattern for almost every situation. Should we use them whenever we can? Of course not.
Design patterns improve our code in theory. In practice you will find plenty of them misused or half-implemented, usually because someone learned a pattern and then applied it everywhere. Working out where a pattern belongs is the hard part. Typing it out is the easy part.
You can find an implementation of any pattern anywhere on the internet, often several implementations of the same one. But if you implement a pattern for the sake of the pattern, you will usually do more damage to your project than good. So every article below explains the problem first, then the pattern, then a working example you can run.
The first three sections below follow the original Gang of Four grouping. After that come the principles the patterns rest on, the ones that turn up in data access and domain code, the architectural patterns that shape a whole system, and the refactoring articles, which show the code smells that usually mean a pattern is missing.
Creational Design Patterns
These cover construction, so the code asking for an object does not have to know how to build one.
- Builder and Fluent Builder
- Measure Application Performance in .NET Using IMeterFactory
- Factory Method
- Abstract Factory Design Pattern
- Singleton
- Fluent Builder With Recursive Generics
- Faceted Builder
Structural Design Patterns
How objects are composed. Change the shape of a thing here and the code using it can stay as it is.
Behavioral Design Patterns
Who talks to whom, and who is responsible for what.
- MediatR Publish and Send Methods
- Mediator Design Pattern
- Chain of Responsibility Design Pattern
- Strategy Design Pattern
- Template Method Design Pattern
- Visitor Design Pattern
- Observer Design Pattern
- Command
SOLID Principles
SOLID gets filed alongside the patterns, but it is the five principles most of them are trying to satisfy. Read these first if the patterns feel arbitrary.
- Open Closed Principle
- Liskov Substitution Principle
- Single Responsibility Principle
- Dependency Inversion Principle
- Interface Segregation Principle
Domain and Data Access Patterns
These come up constantly in business applications, usually around the database and the domain model.
- Understanding the Unit of Work Pattern
- Aggregate Design
- Value Objects
- Saga Pattern With NServiceBus
- Using Keyed Services to Resolve Dependencies
Architectural Patterns
These shape a whole system, so the trade-offs are bigger and much harder to undo. The articles spend more time on when to walk away.
- Onion vs Clean Architecture
- Clean Architecture
- Architecture Tests With NetArchTest.Rules
- Plugin Architecture Pattern
- Broker Architectural Pattern
- Pipes and Filters Architectural Pattern
- Event-Driven Architecture
- Client-Server Architectural Pattern
- Service-Oriented Architecture
- Strangler Fig Architectural Pattern
- Monolith and Distributed Monolith Architectural Patterns
Refactoring and Code Quality
Refactoring is how you get from the code you have to the code a pattern describes. These work through the smells that usually come first.
- Modular Monolith Architecture
- 22 C# Best Practices
- Common C# Programming Mistakes
- Refactoring Bloated Code
- Create Clean Guard Clauses With GuardClauses
- Refactoring Dispensables
- Refactoring Object-Orientation Abusers
- Refactoring Change Preventers
- Refactoring Couplers
Where to Go Next
Once the patterns make sense, these go deeper on the language features they are built from:
If two patterns both look like they fit, the problem is usually not yet clear enough to need either. Write the plain version, and reach for a pattern when the plain version starts to hurt.
