Author image

Registry - Dependency Injection Container Design Pattern


Difficulty:
2/5


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

  1. Create your desired classes, deriving from an IClass hierarchy
  2. Create the Registry-DIC class following the template in this tutorial
  3. 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.

The difference is that Singleton allows only one instance of a given class, while Registry holds a 1-1 map of keys to instances. Registry's principal purpose is to allow you to navigate to associated objects and disallow needless duplications, so even though there is some overlap, they are used for completely different purposes and solve different problems!

I used Windows, Visual Studio and C++17 to build the project.

Github

Github repository link.


0 likes