GeezerVison is showing thinkinginpython.com — Pattern Catalog · Thinking in Python
Index
Chapter 39
Pattern Catalog
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.
| If the problem is |
Look at |
| Creating objects without naming their classes |
Abstract Factory, Builder, Factory
Method, Prototype, Registry,
Plugin |
| Controlling access to another object |
Proxy |
| Adding behavior to an object without changing its class |
Decorator |
| Converting one interface into another a client expects |
Adapter |
| Simplifying access to a subsystem |
Façade |
| Proxying a service’s calls from a helper process |
Ambassador, Sidecar |
| Swapping an algorithm at runtime |
Strategy |
| Varying some steps of an algorithm while its outline stays
the same |
Template Method |
| Encapsulating a request as an object |
Command |
| Passing a request along a chain until something handles
it |
Chain of Responsibility |
| Changing behavior when an object’s internal state
changes |
State |
| Driving an object through a known set of states |
State Machine |
| Adding an operation without changing the classes it
visits |
Visitor |
| Resolving behavior from the runtime types of two
objects |
Double Dispatch |
| Stepping through a collection’s elements in order |
Iterator |
| Structuring recursive or tree-shaped data |
Composite, Interpreter,
Visitor |
| Keeping the number of objects down |
Flyweight, Multiton, Object Pool,
Singleton |
| Saving and restoring state |
Memento, Event Sourcing |
| Reacting to change |
Observer, Publish-Subscribe Channel,
Model-View-Controller |
| Coordinating concurrent work |
Thread Pool, Producer-Consumer,
Future/Promise, Structured Concurrency,
Active Object, Reactor |
| Keeping a program running when a dependency fails |
Circuit Breaker, Retry, Bulkhead,
Timeout, Dead Letter Channel |
| Returning several named values from one call |
Messenger, Data Transfer Object |
| Moving data across a boundary |
Data Transfer Object, Message Translator,
Gateway, Data Mapper |
| Persisting domain objects to a database |
Active Record, Data Mapper,
Repository, Table Module, Lazy Load,
Unit of Work, Identity Map |
| Organizing application logic by request or use case |
Transaction Script, Domain Model,
Service Layer, Front Controller |
| Modeling a value, amount, or special case instead of
null |
Value Object, Money, Special
Case, Null Object |
| Routing or transforming a message |
Content-Based Router, Message Router,
Splitter, Aggregator |
| Connecting an application to a messaging system |
Message, Message Channel, Message
Endpoint, Point-to-Point Channel |
| Supplying a collaborator from outside, or looking one up in
a registry |
Dependency Injection, Service Locator,
Strategy |
Creational (GoF)
| Pattern |
Intent |
| Abstract
Factory |
Create families of related objects without naming concrete
classes. |
| Builder |
Build a complex object in steps, keeping the assembly
separate from the finished object. |
| Factory
Method |
Defer instantiation to a method so subclasses choose the
concrete type. |
| Prototype |
Create new objects by cloning an existing instance. |
| Singleton |
Ensure a class has one instance with a single point of
access. |
Structural (GoF)
| Pattern |
Intent |
| Adapter |
Convert one interface into another a client expects. |
| Bridge |
Separate an abstraction from its implementation so both vary
independently. |
| Composite |
Treat individual objects and compositions of them uniformly
through a tree. |
| Decorator |
Attach responsibilities to an object dynamically by wrapping
it. |
| Façade |
Provide one simplified interface to a subsystem. |
| Flyweight |
Share fine-grained objects to support large numbers of them
efficiently. |
| Proxy |
Provide a surrogate that controls access to another
object. |
Behavioral (GoF)
| Pattern |
Intent |
| Chain
of Responsibility |
Pass a request along a chain until a handler processes
it. |
| Command |
Encapsulate a request as an object, enabling queues,
logging, and undo. |
| Interpreter |
Represent a grammar and evaluate sentences written in
it. |
| Iterator |
Access the elements of a collection in order without
exposing its structure. |
| Mediator |
Route communication between objects through one place to
reduce coupling. |
| Memento |
Capture and restore an object’s state without breaking
encapsulation. |
| Observer |
Notify dependents automatically when an object changes
state. |
| State |
Change an object’s behavior when its internal state
changes. |
| Strategy |
Make a family of algorithms interchangeable at runtime. |
| Template
Method |
Define an algorithm’s skeleton, letting subclasses fill in
steps. |
| Visitor |
Add operations to an object structure without changing its
classes. |
Concurrency (POSA and
others)
| Pattern |
Intent |
| Active Object |
Decouple a method call from its execution by giving the
object its own thread. |
| Balking |
Refuse an action when the object is in the wrong state. |
| Double-Checked
Locking |
Skip the lock once a lazily initialized shared resource
exists. |
| Future/Promise |
Represent a result that becomes available later. |
| Guarded Suspension |
Block a call until a precondition becomes true. |
| Half-Sync/Half-Async |
Separate synchronous and asynchronous work, joined by a
queue. |
| Leader/Followers |
Let a pool of threads take turns receiving and handling
events. |
| Monitor Object |
Serialize access so one method at a time runs on an
object. |
| Proactor |
Dispatch the completion of asynchronous operations to
handlers. |
| Producer-Consumer |
Decouple work creation from processing through a shared
queue. |
| Reactor |
Dispatch incoming requests to handlers synchronously as they
arrive. |
| Read-Write Lock |
Allow concurrent readers but exclusive writers. |
| Structured
Concurrency |
Tie concurrent tasks to a scope that exits only after every
task finishes, cancelling the rest when one fails. |
| Thread
Pool |
Reuse a set number of worker threads across many tasks. |
| Thread-Specific
Storage |
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.
Architectural (POSA)
| Pattern |
Intent |
| Blackboard |
Let independent components cooperate through a shared data
store. |
| Broker |
Coordinate requests and replies between distributed
components. |
| Layers |
Stack responsibilities so each layer uses only the one
beneath it. |
| Microkernel |
Keep a minimal core and add capability through
plug-ins. |
| Model-View-Controller
(MVC) |
Separate data, presentation, and input handling. |
| Pipes
and Filters |
Process a stream through a chain of independent
transforms. |
| Presentation-Abstraction-Control (PAC) |
Build interactive systems from cooperating agents, each
split three ways. |
| Reflection |
Let a program inspect and adjust its structure at
runtime. |
Enterprise Application
(Fowler)
| Pattern |
Intent |
| Active Record |
Wrap a table row in an object that loads and saves
itself. |
| Data Mapper |
Move data between objects and the database, so neither names
the other. |
| Data
Transfer Object (DTO) |
Carry data between processes in one batched object. |
| Domain Model |
Model business logic as a graph of objects. |
| Front Controller |
Route all requests through a single handler. |
| Gateway |
Wrap access to an external system in a simple
interface. |
| Identity Map |
Load each object once per session. |
| Lazy Load |
Defer loading a persisted object until something needs
it. |
| Money |
Represent monetary amounts together with their
currency. |
| Plugin |
Select an implementation by naming its class in
configuration rather than in code. |
| Registry |
Keep one well-known object where the rest of the program
looks up services or data. |
| Repository |
Stand between the domain and the data store, presenting
stored objects as a queryable collection. |
| Service Layer |
Define an application boundary as a set of operations. |
| Special
Case |
Supply a subclass for a particular case, such as a missing
or unknown customer, instead of a conditional at every use. |
| Table Module |
Let one class handle all rows of a table. |
| Transaction Script |
Organize logic as one procedure per request. |
| Unit of Work |
Track changes in a transaction and commit them
together. |
| Value
Object |
Model a small value as an immutable object compared by
value, not identity. |
Integration
and Messaging (Hohpe and Woolf)
| Pattern |
Intent |
| Aggregator |
Combine related messages into one. |
| Content-Based Router |
Route by inspecting the message content. |
| Dead Letter Channel |
Hold messages the messaging system cannot deliver. |
| Message |
Package data to send over a channel. |
| Message Channel |
Connect senders and receivers through a logical pipe. |
| Message Endpoint |
Connect an application to the messaging system. |
| Message Router |
Send a message to a destination chosen at runtime. |
| Message Translator |
Convert a message from one format to another. |
| Point-to-Point Channel |
Deliver a message to exactly one receiver. |
| Publish-Subscribe
Channel |
Broadcast a message to every subscriber to its topic. |
| Splitter |
Break one message into several. |
Distributed and Cloud
| Pattern |
Intent |
| Ambassador |
Route a service’s outbound calls through a helper. |
| API Gateway |
Offer one entry point in front of many services. |
| Bulkhead |
Isolate resources so one failure leaves the rest of the
system running. |
| Circuit Breaker |
Stop calling a failing service until it recovers. |
| Command Query Responsibility Segregation
(CQRS) |
Separate the read model from the write model. |
| Event Sourcing |
Store state as a log of events instead of current
values. |
| Retry |
Re-attempt a failed operation, often with backoff. |
| Saga |
Run a long transaction as a series of compensable
steps. |
| Service Discovery |
Locate service instances dynamically. |
| Sidecar |
Attach helper functionality to a service as a separate
process. |
| Strangler Fig |
Replace a legacy system incrementally by routing around
it. |
| Timeout |
Bound how long to wait for a response. |
Language and
Implementation Idioms
| Pattern |
Intent |
| Curiously Recurring Template Pattern (CRTP) |
Parameterize a base class by the subclass that inherits from
it. |
| Marker Interface |
Tag a class with an empty interface to signal a
capability. |
| Mixin |
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. |
| Resource
Acquisition Is Initialization (RAII) |
Acquire a resource in a constructor and release it in the
matching destructor. |
Functional Idioms
| Pattern |
Intent |
| Function
Composition |
Build a function by passing one function’s output to the
next. |
| Memoization |
Cache a function’s results keyed by its arguments. |
| Monad |
Sequence computations inside a context such as optionality,
error, or async. |
| Partial
Application |
Preset some of a function’s arguments and get a function
expecting the rest. |
Dependency Supply
| Pattern |
Intent |
| Dependency
Injection |
Supply an object’s collaborators from outside it. |
| Inversion
of Control |
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. |
| Service
Locator |
Look up dependencies through a central registry. |
Other Patterns and
Idioms
| Pattern |
Intent |
| Borg
(Monostate) |
Let every instance share one set of state instead of sharing
one instance. |
| Double
Dispatch |
Resolve behavior from the runtime types of two objects,
through two calls. |
| Fluent
Interface |
Return the receiver from each method so calls chain into one
expression. |
| Function
Object |
Decouple the choice of function to call from the place that
calls it. |
| Lazy
Initialization |
Create a value on first use. |
| Messenger |
Bundle values into one object with named attributes.
Messenger is the in-process form of Data Transfer
Object. |
| Multiton |
Manage a pool of singletons, one per key. |
| Null
Object |
Use an object with neutral behavior in place of null. |
| Object
Pool |
Reuse expensive objects from a managed pool. |
| Specification |
Encapsulate a rule as a predicate that combines with
others. |
| State
Machine |
Drive an object through a known set of states in response to
inputs. |
| Surrogate |
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.
| Pattern |
What Python gives you instead |
| Iterator |
The iteration protocol, called for you by
for |
| Singleton |
A module, imported once and cached |
| Factory
Method |
A dictionary of classes, since a class is an object |
| Prototype |
copy.deepcopy() and
copy.replace() |
| Strategy |
A function passed as an argument |
| Command |
A function saved to run later |
| Chain
of Responsibility |
A list of functions, tried in order |
| Visitor |
functools.singledispatch, or a
match over a union of types |
| Flyweight |
Interned strings and cached small integers |
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.
|