85 lines
6.9 KiB
Markdown
85 lines
6.9 KiB
Markdown
# 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.
|