GoF (Gang of Four) Design Patterns are 23 reusable solutions to recurring object-oriented design problems, first documented in Design Patterns: Elements of Reusable Object-Oriented Software (1994) by Gamma, Helm, Johnson, and Vlissides. They provide a shared vocabulary for design intent — when a team says “let’s use a Strategy here,” everyone immediately understands the tradeoffs without long explanations. Patterns are not copy-paste code; they’re templates for solving classes of problems. This section covers all 23 GoF patterns organized by category, each with production C# examples showing the problem without the pattern, the transformation with it, and the .NET built-ins that already implement it — connecting new knowledge to things you use daily.

Choose a pattern by intent and cost

Start from the pressure in the code, not a pattern name. Introduce the smallest pattern that makes a real variation or responsibility boundary explicit.

PressureCandidateWhat it buysWhat it costsReject it when
Construction selects among related product familiesAbstract FactoryKeeps compatible products and construction policy togetherFactory interfaces multiply with product familiesThere is one concrete family
Construction has many ordered or optional inputsBuilderNames construction steps and protects invariantsExtra builder type and duplicated API surfaceA constructor or options record stays readable
Existing interface does not match a consumerAdapterLocalizes translation at one boundaryAnother abstraction to test and maintainYou control both sides and can align the contract directly
Add behavior around one object without subclass combinationsDecoratorComposes responsibilities at runtimeNested wrappers obscure execution orderOne direct implementation has no meaningful variants
Choose one interchangeable algorithmStrategyMakes policy selection explicit and testableMore types or delegatesA small conditional is stable and clearer
Notify unknown dependents about state changesObserverDecouples publisher from subscriber setOrdering, lifetime, and error handling become indirectThere is one required caller that should invoke directly
Encapsulate a request for queuing, undo, or dispatchCommandTurns an operation into data with explicit executionBoilerplate around simple method callsNo delayed, logged, retried, or reversible execution exists

Patterns can share structure while serving different intent. Proxy and Decorator both wrap an interface, but Proxy controls access to another object while Decorator adds responsibility. State and Strategy both delegate behavior, but State transitions internally while Strategy is selected as a policy. Name the intent and deletion condition in the design review; if the second variation disappears, collapse the abstraction.

Questions

References

4 items under this folder.