Skip to content

Registry Pattern — Centralized Object Lookup and Storage

DodaTech Updated 2026-06-24 4 min read

What You'll Learn

You will learn how the Registry pattern provides a single, well-known location for storing and retrieving shared objects, offering a controlled alternative to ad-hoc global state. You will understand when to use Registry versus Dependency Injection.

Why It Matters

Applications often need access to shared services like database connections, configuration, or caches. Passing these through every constructor creates parameter pollution. Using global variables is unsafe and untestable. Registry strikes a balance — a single, controlled point of access that can be swapped during testing. For testing, you replace services in the registry with mocks; in production, the same registry holds real implementations.

Real-World Use

Enterprise frameworks use ServiceRegistry or ServiceLocator patterns to hold references to application services. DodaTech's extension system maintains a registry of installed plugins keyed by name, allowing any part of the application to look up a plugin by its identifier without coupling to its location.

The Pattern

Registry provides set and get methods, often with Singleton access. Entries are stored in a map keyed by name or type. The registry can be populated at startup and queried throughout the application lifecycle.

class ServiceRegistry:
    _instance = None
    _services = {}

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._services = {}
        return cls._instance

    def register(self, name: str, service):
        self._services[name] = service

    def get(self, name: str):
        service = self._services.get(name)
        if service is None:
            raise KeyError(f"Service '{name}' not registered")
        return service

    def has(self, name: str) -> bool:
        return name in self._services

    def registered_names(self) -> list:
        return list(self._services.keys())

class ConfigService:
    def __init__(self):
        self._config = {}

    def load(self, config: dict):
        self._config = config

    def get(self, key: str, default=None):
        return self._config.get(key, default)

class CacheService:
    def __init__(self):
        self._cache = {}

    def put(self, key: str, value):
        self._cache[key] = value

    def get(self, key: str):
        return self._cache.get(key)
registry = ServiceRegistry()

config = ConfigService()
config.load({"db_host": "localhost", "db_port": 5432})
registry.register("config", config)

cache = CacheService()
registry.register("cache", cache)

retrieved_config = registry.get("config")
print("DB Host:", retrieved_config.get("db_host"))

registry.get("cache").put("user:1", "Alice")
print("Cached user:", registry.get("cache").get("user:1"))

print("Registered services:", registry.registered_names())
DB Host: localhost
Cached user: Alice
Registered services: ['config', 'cache']

Structure

classDiagram
    class Registry {
        -instance: Registry
        -services: Map
        +register(name, service)
        +get(name): Service
        +has(name): bool
        +registeredNames(): List
    }
    class Service {
        <>
    }
    class ServiceA {
        +operation()
    }
    class ServiceB {
        +operation()
    }
    class Client {
        +doWork()
    }
    Registry --> "*" Service : manages
    ServiceA ..|> Service
    ServiceB ..|> Service
    Client --> Registry : queries

Real-World Usage

  • Spring ApplicationContext — the IoC container acts as a registry for all managed beans.
  • Java JNDI — Java Naming and Directory Interface is a registry for distributed objects and services.
  • Python importlib — the module cache (sys.modules) is a registry of loaded modules.
  • WordPress WP_Object_Registry — a global registry for storing and retrieving object instances.
  • ETL tools — DodaTech's connector registry maps data source types (Postgres, S3, BigQuery) to their handler implementations.
  • Singleton — the Registry itself is usually a Singleton.
  • Service Locator is a related pattern — Registry is a simpler form.
  • Dependency Injection is often preferred over Registry for explicit dependency management.
  • Abstract Factory can be registered in a Registry for runtime product selection.
  • Flyweight uses a registry-like structure to share objects.

Pros and Cons

Pros Cons
Single, well-known access point for shared objects Introduces global mutable state
Eliminates constructor parameter chains Testing is harder — services must be replaced in the registry
Runtime flexibility — services can be swapped No compile-time safety — lookups fail at runtime if not registered
Centralised lifecycle management Can hide dependencies, making code harder to reason about
Easy to add interceptors (logging, metrics) Thread Safety must be carefully managed
Simple to understand and implement Overuse leads to implicit, untraceable dependencies

The ServiceRegistry combines Singleton with a key-value store. Services are registered by name at startup and retrieved by name at runtime. The raise KeyError on missing services fails fast — an important design choice that prevents silent failures when a service is not registered.

Practice Questions

  1. How would you make a Registry thread-safe without a global lock?
  2. Compare Registry with Dependency Injection — when would you prefer one over the other?
  3. Implement a scoped registry where services are partitioned by tenant or request context.
  4. How would you add lifecycle callbacks to the Registry (e.g., initialize services on registration, clean up on removal)?

Challenge

Implement a registry that supports lazy service creation — instead of registering an instance, register a Factory function. The service is created on first access and cached for subsequent requests.

Real-World Task

Use DodaTech's service graph explorer to visualise the dependency relationships in your application. If you find many modules reaching into a global registry, consider migrating those dependencies to explicit injection.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro