You will encounter most patterns first as a name someone uses in
a design review, not as code. This catalog gives each name a
one-line intent, so you can place it and look it up.
This chapter gathers the original
Design Patterns (GoF) set, along with other patterns
that the literature documents widely. It draws from
Pattern-Oriented Software Architecture (POSA, Buschmann
et al.), Patterns of Enterprise Application
Architecture (Fowler), Enterprise Integration
Patterns (Hohpe and Woolf), and the common distributed and
cloud patterns that emerged later.
Listing a pattern here does not recommend it. Many overlap,
some solve the same problem in different ways, and several exist
only to work around limits of a particular language. The body of
this book argues that those workarounds often dissolve
in Python.
One overlapping pair is State and
State
Machine. State changes an object’s behavior
when its internal state changes. The client chooses each new
state. State Machine builds on State and
drives an object through a known set of states in response to
inputs. The client supplies the inputs. The machine chooses each
next state.
The tables follow each source’s own
grouping. One of those groupings is GoF’s Creational/Structural/Behavioral
split, which the Design Patterns
chapter accepts for Creational and questions for
Structural and Behavioral. A few idioms below
belong to no single source. They sit in three groups by what
they share: language and implementation idioms (most of them
tied to C++ or Java’s limits), functional idioms, and dependency
supply (patterns that supply a collaborator from outside).
Everything else sits in Other Patterns and Idioms,
a catch-all section. The source and group tables list their rows
alphabetically. GoF lists the classic patterns in the same
order.
When this book covers a pattern, its name links to that
coverage. A name without a link leaves that pattern to the
literature.
Finding a Pattern by
Problem
The tables below group by source, so use this section’s table
when you know the problem but not the name.
Give each thread its own copy of a value.
ContextVar scopes the value to the context
instead.
The name Reactor says
little about what the pattern does. The pattern is a dispatcher.
One loop waits on many event sources and calls the handler
registered for each event. The original description of
Reactor lists Dispatcher as another name for
the pattern. This catalog keeps the name Reactor
because the literature and the libraries use it. Both asyncio’s
SelectorEventLoop and Twisted’s
reactor implement Reactor.
Proactor is the counterpart of Reactor for
completed operations. A Reactor calls a handler when a
source is ready, and the handler then performs the read or
write. A Proactor starts the read or write and calls
the handler once the operation has finished. On Windows,
asyncio’s default event loop is a Proactor,
ProactorEventLoop, built on the operating system’s
I/O completion ports.
Add reusable behavior through multiple inheritance.
Pointer to Implementation (Pimpl)
Store a class’s implementation in a separate object reached
through a pointer, so the implementation can change while
clients keep their compiled code.
Let a framework call your code rather than the reverse.
Dependency Injection applies Inversion of
Control to an object’s collaborators. The usual alternative
to Dependency Injection is Service Locator.
Service Locator keeps control in your code, which asks
a registry for each collaborator.
Put a stand-in in front of the object that does the work.
Proxy and State are both forms of
Surrogate.
Type Object
Represent a “kind of” thing as data rather than a
subclass.
Patterns Python Absorbed
Several entries above are in the catalog because the
literature documents them, not because you need to write them.
For each of them, Python provides a language feature or a
standard-library tool in place of the classes the pattern
describes.
Each link leads to the section that shows the Python form of
its pattern.
Python supplies each pattern’s structure, but the pattern’s
intent remains. You still choose which algorithm to pass, which
action to save for later, or which values to share.