registry pattern
The registry pattern is a design pattern that keeps a central lookup table mapping keys to objects, so any part of a program can find a component by name instead of holding a direct reference to it.
Note: Martin Fowler cataloged the pattern in Patterns of Enterprise Application Architecture as “a well-known object that other objects can use to find common objects and services.”
A registry needs only two operations: one that stores a value under a key, and one that returns the value for a given key. The keys are usually strings or types, and the values range from a single shared service to whole classes waiting to be instantiated.
When the values are classes, a factory usually wraps the registry, looking up the key and returning a new instance. The registry sits at a known location, such as a module-level dictionary, so callers reach it without receiving it as an argument.
Its most common use is a plugin architecture. Each implementation registers itself under a name as it loads, and the application resolves that name later. This inverts the usual direction of a dependency, because the core code never imports the plugins. Adding a new implementation then means adding a file rather than editing a hand-written chain of conditionals:
Registration itself happens in a few standard ways:
- Explicit call: The registering module calls a function such as
register(key, value)at import time. - Decorator: A decorator attached to a class or function stores the object under a key and returns it unchanged.
- Subclass hook: A base class records every subclass automatically as each one is defined, through a metaclass or
.__init_subclass__(). - Entry point: The packaging metadata of an installed distribution declares the implementation, which lets a separate package extend the application.
Python builds registries into several standard library tools. The functools module’s singledispatch() exposes a read-only .registry mapping of types to implementations, filled by its .register() decorator. The codecs module keeps a codec registry that lookup() searches by encoding name.
Because a registry is reachable from everywhere, it attracts the same criticisms as a singleton. It holds mutable global state and hides dependencies that dependency injection would make explicit. A missing key also surfaces at runtime rather than at import time, and registration order matters, since a lookup that runs before the registering module is imported finds nothing.
Step through the import order of a small plugin application below to watch the registry fill one entry at a time, then resolve a name before and after its module loads:
Related Resources
Tutorial
The Factory Method Pattern and Its Implementation in Python
In this Python tutorial, you'll learn about the Factory Method design pattern and its implementation. You'll understand the components of Factory Method, when to use it, and how to modify existing code to leverage it. You'll also see a general purpose implementation of Factory Method in Python.
For additional information on related topics, take a look at the following resources:
- Implementing the Factory Method Pattern in Python (Course)
- Primer on Python Decorators (Tutorial)
- SOLID Design Principles: Improve Object-Oriented Code in Python (Tutorial)
- Object-Oriented Programming (OOP) in Python (Tutorial)
- Dictionaries in Python (Tutorial)
- The Factory Method Pattern and Its Implementation in Python (Quiz)
- Python Decorators 101 (Course)
- Primer on Python Decorators (Quiz)
- Design and Guidance: Object-Oriented Programming in Python (Course)
- SOLID Design Principles: Improve Object-Oriented Code in Python (Quiz)
- A Conceptual Primer on OOP in Python (Course)
- Intro to Object-Oriented Programming (OOP) in Python (Course)
- Object-Oriented Programming (OOP) in Python (Quiz)
- Using Dictionaries in Python (Course)
- Dictionaries in Python (Quiz)
By Martin Breuss • Updated Aug. 26, 2026