You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-[Examples and Use Cases](#examples-and-use-cases)
26
+
-[How to Contribute](#how-to-contribute)
27
+
-[Further Reading](#further-reading)
23
28
-[License](#license)
24
29
-[Contact](#contact)
25
30
@@ -77,6 +82,34 @@ Patterns offer ways to handle changing requirements and evolving designs by deco
77
82
## Why Use Design Patterns?
78
83
Design patterns act as a toolbox of proven solutions, helping developers create better, more efficient, and maintainable software. They offer a structured approach to problem-solving, improve code readability, and facilitate collaboration among team members.
79
84
85
+
## Overview Table of GoF Patterns
86
+
87
+
| Pattern | Category | Description |
88
+
|---------|----------|-------------|
89
+
|**Abstract Factory**| Creational | Provide an interface for creating families of related or dependent objects without specifying their concrete classes. |
90
+
|**Builder**| Creational | Separate the construction of a complex object from its representation so that the same process can create different representations. |
91
+
|**Factory Method**| Creational | Define an interface for object creation, but let subclasses decide which class to instantiate. |
92
+
|**Prototype**| Creational | Create new objects by copying an existing object (prototype) rather than creating from scratch. |
93
+
|**Singleton**| Creational | Ensure a class has only one instance, and provide a global point of access to it. |
94
+
|**Adapter**| Structural | Allow incompatible interfaces to work together by wrapping one with an adapter. |
95
+
|**Bridge**| Structural | Decouple an abstraction from its implementation so the two can vary independently. |
96
+
|**Composite**| Structural | Compose objects into tree structures to represent part-whole hierarchies; clients treat individual objects and compositions uniformly. |
97
+
|**Decorator**| Structural | Attach additional responsibilities to objects dynamically. |
98
+
|**Facade**| Structural | Provide a unified interface to a set of interfaces in a subsystem. |
99
+
|**Flyweight**| Structural | Use sharing to support large numbers of fine-grained objects efficiently. |
100
+
|**Proxy**| Structural | Provide a surrogate or placeholder for another object to control access or defer costly operations. |
101
+
|**Chain of Responsibility**| Behavioral | Allow a request to be passed along a chain of handlers until one handles it. |
102
+
|**Command**| Behavioral | Encapsulate a request as an object, thereby letting you parameterize clients with queues, requests, and operations. |
103
+
|**Interpreter**| Behavioral | Define a representation for a grammar of a language, and an interpreter to deal with this grammar. |
104
+
|**Iterator**| Behavioral | Provide a way to access elements of an aggregate object sequentially without exposing its underlying representation. |
105
+
|**Mediator**| Behavioral | Define an object that encapsulates how a set of objects interact. |
106
+
|**Memento**| Behavioral | Capture and externalize an object’s internal state so that it can be restored later, without breaking encapsulation. |
107
+
|**Observer**| Behavioral | Define a one-to-many dependency so that when one object changes state, all its dependents are notified. |
108
+
|**State**| Behavioral | Allow an object to alter its behavior when its internal state changes; object appears to change class. |
109
+
|**Strategy**| Behavioral | Define a family of algorithms, encapsulate each one, and make them interchangeable. |
110
+
|**Template Method**| Behavioral | Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. |
111
+
|**Visitor**| Behavioral | Represent an operation to be performed on elements of an object structure without changing the classes of the elements. |
112
+
80
113
## Patterns vs. Anti-patterns
81
114
Design patterns and anti-patterns play crucial roles in software development, each representing opposing approaches to solving programming challenges:
82
115
-**Design Patterns**:
@@ -94,10 +127,49 @@ Design patterns and anti-patterns play crucial roles in software development, ea
94
127
- Poor understanding and ineffective communication among team members.
95
128
- Spread of poor design practices, causing numerous bugs and making new code integration challenging.
96
129
130
+
## When to Use or Avoid Each Pattern
131
+
| Pattern | When to Use | When to Avoid |
132
+
|---------|-------------|---------------|
133
+
|**Abstract Factory**| When you need to create families of related objects without depending on concrete classes. | If you only need a few objects and don’t need family consistency. |
134
+
|**Builder**| When constructing a complex object step by step with different representations. | If the object is simple and doesn’t need stepwise construction. |
135
+
|**Factory Method**| When subclasses should decide which concrete class to instantiate. | If you don’t need flexibility in instantiation. |
136
+
|**Prototype**| When creating new objects by cloning existing ones is cheaper than creating from scratch. | If objects are simple or cloning is more expensive than direct creation. |
137
+
|**Singleton**| When exactly one instance must exist and be globally accessible. | If global state leads to hidden dependencies or testing becomes hard. |
138
+
|**Adapter**| When you need to make incompatible interfaces work together. | If you can refactor the code to use a common interface instead. |
139
+
|**Bridge**| When you want to decouple abstraction from implementation so both can vary. | If the hierarchy is stable and won’t evolve separately. |
140
+
|**Composite**| When working with tree structures (part-whole hierarchies) and want uniform access. | If the structure is flat and simple, no hierarchy needed. |
141
+
|**Decorator**| When you want to add behavior dynamically without modifying classes. | If object composition makes debugging/maintenance too complex. |
142
+
|**Facade**| When you want to simplify a complex subsystem with a unified interface. | If a simple wrapper hides too much functionality needed by clients. |
143
+
|**Flyweight**| When you need to handle many similar objects efficiently by sharing state. | If objects are unique and sharing state gives no benefit. |
144
+
|**Proxy**| When you want a placeholder to control access (e.g., lazy load, security). | If indirection adds unnecessary complexity or overhead. |
145
+
|**Chain of Responsibility**| When multiple handlers can process a request without hardcoding sender–receiver. | If request flow must be predictable and explicit. |
146
+
|**Command**| When you need to encapsulate requests, support undo/redo, or queue/log actions. | If direct method calls are simpler and sufficient. |
147
+
|**Interpreter**| When you have a grammar to interpret and it’s relatively simple. | If grammar is complex — use a parser/DSL instead. |
148
+
|**Iterator**| When you want sequential access to elements without exposing structure. | If simple loops over collections are enough. |
149
+
|**Mediator**| When you want to centralize and simplify complex communications between objects. | If communication is simple and a mediator adds indirection. |
150
+
|**Memento**| When you need to save and restore object state without exposing internals. | If state saving is too costly in memory or performance. |
151
+
|**Observer**| When you want one-to-many notifications of state changes. | If frequent updates cause performance issues or cascading changes. |
152
+
|**State**| When an object’s behavior should change based on internal state. | If state changes are rare or can be handled with conditionals. |
153
+
|**Strategy**| When you need interchangeable algorithms encapsulated behind a common interface. | If only one algorithm exists and will not change. |
154
+
|**Template Method**| When you want to define the skeleton of an algorithm but let subclasses fill steps. | If subclassing leads to rigid inheritance and reduced flexibility. |
155
+
|**Visitor**| When you need to perform operations on object structures without modifying them. | If the object structure changes often — adding visitors becomes painful. |
156
+
97
157
## .NET and Design Patterns
98
158
The .NET platform, especially with C#, offers rich language features (like delegates, LINQ, async/await, and dependency injection) that make many design patterns more expressive and efficient to implement. Patterns like Dependency Injection, Singleton, Factory, and Observer are commonly used in .NET-based enterprise solutions and are well-supported by frameworks like ASP.NET Core and libraries like `Microsoft.Extensions.*`
99
159
In this repository, each pattern is demonstrated using idiomatic C# to reflect best practices in the .NET ecosystem.
0 commit comments