注册模式 Registry Pattern 注册树模式 注册器模式 结构型设计模式
Registry Pattern - GeeksforGeeks
public class Registry { private static final Registry INSTANCE = new Registry(); private Map<String, Object> registryMap; private Registry() { registryMap = new HashMap<>(); } public static Registry getInstance() { return INSTANCE; } public void register(String key, Object obj) { registryMap.put(key, obj); } public Object get(String key) { return registryMap.get(key); } }
public class Registry { private Map<String, Service> services = new HashMap<>(); public void registerService(String name, Service service) { services.put(name, service); } public Service getService(String name) { return services.get(name); } } public class RegistrationPatternDemo { public static void main(String[] args) { Registry registry = new Registry(); registry.registerService("serviceA", new ConcreteServiceA()); registry.registerService("serviceB", new ConcreteServiceB()); Service serviceA = registry.getService("serviceA"); serviceA.execute(); // 输出: ConcreteServiceA is executing. Service serviceB = registry.getService("serviceB"); serviceB.execute(); // 输出: ConcreteServiceB is executing. } }
注册模式的核心思想是将对象的创建和管理集中到一个注册表中,用户无需直接使用 new 关键字实例化对象,而是通过注册表注册和获取对象实例。
这种模式也被称为注册树模式或注册器模式,属于结构型设计模式。
Importance of the Registry Pattern
The Registry Pattern is important in software design for several reasons:
- Centralized Management: By providing a centralized repository for object instances, the Registry Pattern simplifies the management of shared resources. This centralization makes it easier to control and update the objects, as all interactions go through the registry.
- Decoupling Components: It helps decouple different parts of an application. Components do not need to know the specific classes or how to instantiate the objects they depend on; they simply interact with the registry to obtain these objects. This reduces dependencies and enhances modularity.
- Reusability and Resource Sharing: The pattern promotes reuse of objects and resources. Instead of creating new instances, components can use shared instances managed by the registry, which can lead to better resource utilization and performance improvements.
- Configuration Management: The registry can be configured at runtime, allowing for more flexible and dynamic behavior of the application. This is particularly useful in scenarios where different configurations or environments need different object instances.
- Support for Singleton Pattern: The Registry Pattern can complement the Singleton Pattern by managing single instances of classes in a more flexible and organized way. This helps avoid the limitations and potential issues of hard-coded singletons.
- Improved Testing: With a centralized registry, it becomes easier to mock or replace objects during testing. This enhances testability by allowing test setups to inject mock objects or different configurations through the registry.
Core Components of the Registry Pattern
The Registry Pattern consists of several core components that work together to provide centralized management and access to shared objects. These components include:
- Registry: The central repository where objects are registered and stored. This can be implemented as a class that maintains a collection (such as a dictionary or map) of objects indexed by unique keys. The registry provides methods for registering, retrieving, and possibly unregistering objects.
- Keys/Identifiers: Unique identifiers used to register and retrieve objects from the registry. These can be strings, enums, or any other type that ensures uniqueness within the registry.
- Registered Objects: The actual instances or objects that are stored in the registry. These objects can be of various types, depending on the application’s needs. They are typically resources, services, or shared instances that need to be accessed by multiple components.
- Registration Interface: The methods provided by the registry for adding objects. This interface usually includes methods such as register, add, or put, allowing objects to be stored in the registry with their associated keys.
- Lookup Interface: The methods provided by the registry for retrieving objects. This interface usually includes methods such as get, lookup, or find, which take a key as a parameter and return the corresponding object.
- Initialization and Configuration: The process by which the registry is set up, typically during the application’s startup phase. This can include loading configurations, initializing default objects, and pre-registering certain key objects.
- Exception Handling: Mechanisms to handle cases where an object is not found in the registry, or when an object cannot be registered due to conflicts. This ensures robustness and reliability in accessing shared resources.
How the Registry Pattern Works?
The Registry Pattern works by centralizing the management and access of shared objects or instances within a software application. Here’s how it typically functions:
- Registry Initialization: At the start of the application or when needed, a registry object is instantiated. This registry serves as a centralized repository where objects will be registered and accessed.
- Object Registration: Objects or instances that need to be shared across different parts of the application are registered with the registry. Each object is associated with a unique identifier or key. This registration process typically involves calling a method on the registry (e.g., register(key, object)).
- Centralized Access: Other components or modules within the application can then access these registered objects through the registry. Instead of directly creating or maintaining their own instances of these objects, they retrieve them from the registry using their respective keys (e.g., get(key)).
- Decoupling and Dependency Management: By using the registry, components become decoupled from the specific classes or instances they depend on. They only need to know the keys to access the objects they require, rather than being tightly coupled to the instantiation details of those objects.
- Lifecycle Management: The registry can optionally handle the lifecycle of registered objects. For instance, it may manage singleton instances, ensuring that only one instance of a particular object exists throughout the application.
- Flexibility and Configuration: The registry can be configured dynamically during runtime. This allows for flexibility in swapping out implementations or configurations of objects without modifying the components that use them directly.
- Testing and Mocking: In testing scenarios, the registry facilitates easier unit testing by allowing mock objects or test-specific implementations to be registered instead of real objects. This enhances testability and isolates components for more effective testing.
- Error Handling: The registry typically includes error handling mechanisms to deal with cases where an object with a specified key does not exist or cannot be retrieved. This ensures robustness and reliability in accessing shared resources.
Use Cases of Registry Pattern
The Registry Pattern finds its utility in various scenarios across system design where centralized management and access to shared resources are beneficial. Here are some common use cases where the Registry Pattern can be effectively applied:
- Dependency Injection Containers: Dependency Injection (DI) containers often use a form of the Registry Pattern to manage and provide instances of objects (services or dependencies) to different parts of an application. The registry acts as a central repository where dependencies are registered and then injected into classes or components that require them.
- Service Locators: In large-scale applications, managing multiple service instances efficiently is crucial. A service locator based on the Registry Pattern can store and provide access to various services, ensuring that they are easily discoverable and accessible throughout the system.
- Resource Pools and Factories: When dealing with resources like database connections, threads, or cached objects, a registry can manage their lifecycle and provide efficient pooling mechanisms. This helps in resource management, ensuring that resources are shared and reused effectively across the application.
- Plugin or Extension Systems: Systems that support plugins or extensions benefit from a registry to manage dynamically loaded modules or plugins. Each plugin can register itself with the registry upon initialization, allowing the main application to discover and interact with these extensions dynamically.
- Event Handlers or Listeners: In event-driven architectures, a registry can be used to manage event handlers or listeners. Components register their interest in specific events with the registry, and when events occur, the registry dispatches them to the appropriate handlers, ensuring loose coupling between event sources and listeners.
- Caching Strategies: For caching strategies where different parts of an application need access to cached data, a registry can manage different cache instances based on their keys or types. This allows components to retrieve cached data efficiently without maintaining their own cache instances.

浙公网安备 33010602011771号