Design Patterns in Python
Classic patterns, rewritten the Pythonic way with modules, first-class functions and protocols
- explain why a Python module is already a Singleton;
- replace a Factory class hierarchy with a registry dict of callables;
- implement the Strategy pattern by passing a plain function;
- build an Observer with a list of subscriber callables;
- use
typing.Protocolfor structural typing instead of ABCs.
1. What a pattern is - and Python's twist
A pattern is not a library or a language feature; it is a shape of a solution that keeps re-appearing. Naming those shapes gives a team shared vocabulary: saying "let's use a Strategy here" communicates a whole design in two words.
The catch is that many textbook patterns exist to work around limitations of static, class-only languages. In those languages you cannot pass a function around, so you wrap the function in an object with a single method. Python can pass functions, store them in dicts, and swap behaviour at runtime, so the object wrapper is often unnecessary ceremony. The professional habit is: reach for the simplest tool that expresses the intent, and only add classes when they earn their keep.
| Pattern | Classic OOP form | Pythonic form |
|---|---|---|
| Singleton | class that hides its constructor | a module (already single per process) |
| Factory | creator class hierarchy | a dict registry of callables |
| Strategy | strategy interface + concrete classes | pass a first-class function |
| Observer | subject + observer interfaces | a list of subscriber callbacks |