Registry - Dependency Injection Container Design Pattern
Registry lets you establish a single point of access for objects. Registry is often used as a Dependency Injection container (DIC). A DIC is a singleton class with a hash map container of various singleton types as well as functions querying the map. The queries are done and we return a certain object from the container. This hash-map is the provider of objects originating from a common interface and which they can be reused by whoever's asking (so it's best for them to be of the type std::shared_ptr<Type>
). The objects stay resident inside DIC.
Since we want to avoid duplications, we implicitly want to "share" instances of objects; this requirement is screaming out for shared_ptr.
What will the key and the value of the hashmap represent?
The key identifies an object (for example it can be a hash) and the value is (a pointer to) that object.
If a type of object is requested that hasn't been created previously the DIC creates it and returns it. If the type of object has already been created then it is simply returned; as such avoiding cluttering the codebase with superfluous data.
Design
- Create your desired classes, deriving from an IClass hierarchy
- Create the Registry-DIC class following the template in this tutorial
- Now to create instances/objects of your IClass_Concrete type you have 2 choices
- create it by sharing the instance in DIC using IClass_Concrete::fetch
- or normally via its
IClass_Concrete
constructor (which of course nullifies the purpose of the design pattern)
The implementation of the class is not that trivial. Notice that fetch & generateUid have to be static. Both of them have arguments that equal those of the class' constructor. And if you want to inspect the unique id (uid) of an instance, simply call getUid(); which uses the class' member variables (and perhaps arbitrary extra information) to generate the uid generateUid(args...) of the object.
Registry vs Singleton
The Registry design pattern shares similarities with singleton. Both are about instance control. A Registry is essentially a global object (just like a singleton). It doesn't look like one on the surface. Why? Well the Registry/DIC class instance shouldn't be seen anywhere outside its class. It is only requested inside IClass_Concrete::fetch functions.
I used Windows, Visual Studio and C++17 to build the project.
Github
Github repository link.