Learn how to build, test, deploy, and maintain robust software systems.
A design pattern is a reusable, named solution to a recurring design problem. Patterns are not copy-paste code; they are templates that describe how a problem is commonly solved, so that developers can communicate about them and apply them where they fit. This lesson introduces the three categories of patterns — creational, structural, and behavioral — plus dependency injection, and walks through the Observer pattern in detail. It also stresses the most important skill: knowing when not to use a pattern. Patterns are tools, not goals. The best design is often the simplest one that works.
Dependency injection passes a dependency into an object instead of having the object create it. This makes the object easier to test and reduces coupling.
A publisher holds a list of subscribers and notifies them when an event occurs. Subscribers can be added or removed without the publisher knowing their details — this is loose coupling.
| Pattern | Category | Problem | Typical use |
|---|---|---|---|
| Factory | Creational | Creating objects without coupling to a concrete class | When the exact type is chosen at runtime |
| Adapter | Structural | Incompatible interfaces | Wrapping a third-party library |
| Observer | Behavioral | Notify many objects of a change | Event systems, UI updates |
| Strategy | Behavioral | Swappable algorithms | Payment methods, sorting |
The publisher (bus) does not know what its subscribers are — they are decoupled.
Make the sort key swappable without changing the caller.
(the strategy is the key function)