Files
Design-Patterns/docs/README.md
2026-08-13 22:47:17 -04:00

85 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Design Patterns Cheatsheet
This repo implements seven patterns in C#, cross-referenced with _Design
Patterns: Elements of Reusable Object-Oriented Software_ (Gamma / Helm / Johnson
/ Vlissides — the "Gang of Four", **GoF**) and _Dive Into Design Patterns_
(Alexander Shvets, 2019).
Every code sample comes from the actual project files. Each **Output** block
reflects a real build and run of that project — none of the output is
hand-traced.
## The patterns
**Structural** — how to assemble objects and classes into larger structures.
| Pattern | One-line idea | Repo project |
| ------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------ |
| [Bridge](bridge.md) | Splits one exploding hierarchy into two, joined by composition. | `patterns/bridge/Bridge Example/` |
| [Decorator](decorator.md) | Stacks wrappers, each adding one behavior, all sharing an interface. | `patterns/decorator/ShapeDecorations/` |
| [Facade](facade.md) | Hides a pile of fiddly subsystem classes behind one friendly class. | `patterns/facade/CarEngineFacade/` (+ `CarEngineFacadeRecording/`) |
**Behavioral** — how objects communicate and divide responsibility.
| Pattern | One-line idea | Repo project |
| ----------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| [Mediator](mediator.md) | Stops objects from calling each other directly; routes every call through one go-between. | `patterns/mediator/AirTrafficControl/` |
| [Memento](memento.md) | Lets an object snapshot itself, opaquely, for undo. | `patterns/memento/MementoPattern/` |
| [Observer](observer.md) | Publishes changes to a dynamic list of subscribed listeners. | `patterns/observer/ObserverPattern/` (+ `UpdatedOne/`) |
| [State](state.md) | Replaces a giant `switch` on a state field with one class per state. | `patterns/state/BadCarState/` + `CarState/` (+ `WithStatePattern/`, `WithoutStatePattern/`) |
## Also in here
- **[Cross-pattern comparisons](cross-pattern-comparisons.md)** — the
distinctions most likely to be tested and most likely to cause confusion in
review, such as Bridge vs. State vs. Strategy, Decorator vs. Proxy vs.
Adapter, and Facade vs. Mediator vs. Observer.
- **[Principles these examples keep demonstrating](principles.md)** —
encapsulate what varies, program to an interface, favor composition, the
Single Responsibility Principle, and the Open/Closed Principle.
## Quick reference: GoF intents (verbatim)
| Pattern | GoF Intent | Key structural move |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| **Bridge** | "Decouple an abstraction from its implementation so that the two can vary independently." | Abstraction _has-a_ Implementor |
| **Decorator** | "Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality." | Wrapper _is-a_ AND _has-a_ Component |
| **Facade** | "Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use." | Facade _has-many_ subsystem parts |
| **Mediator** | "Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently." | N×N links → N links to a hub |
| **Memento** | "Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later." | Nested private snapshot class |
| **Observer** | "Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically." | Subject holds `List<IObserver>` |
| **State** | "Allow an object to alter its behavior when its internal state changes. The object will appear to change its class." | Context delegates to a swappable State |
## Before / after pair
One pattern ships with a deliberately bad version alongside the patterned
version. Diffing that pair teaches more than either version alone, so both are
reproduced in full:
- **[State](state.md)** — `BadCarState` (a `switch` inside a `switch`, four
times over) vs. `CarState` (one class per state). The two produce
**byte-identical** output, confirming the refactor changed structure and
nothing else.
## Run these projects
All projects target `net10.0` and are wired into the root `DesignPatterns.slnx`.
Build and run any project directly with the .NET 10 SDK:
```bash
dotnet run --project "patterns/bridge/Bridge Example/Bridge Example.csproj"
```
`CarState`, `BadCarState`, `WithStatePattern`, `WithoutStatePattern`, and
`MementoPattern` read from stdin. Pipe input to them:
```bash
printf 'gas\nturn-clockwise\ngas\nbrake\nturn-counter\nexit\n' | dotnet run --project patterns/state/CarState/CarState.csproj
```
Each `patterns/<pattern>/` folder also holds any in-class recording or
before/after variant alongside the canonical example — for example,
`patterns/facade/CarEngineFacadeRecording/`. The `exercises/` folder holds
material that doesn't map to a specific GoF pattern, such as `ClassIntroExam`, a
pass-by-value-vs-reference demo.