JS Pro Design Patterns - The Singleton Pattern

JS Pro Design Patterns - The Singleton Pattern

The Singleton Pattern

This is one of the most common and useful JavaScript patterns. Basically, it is used to group code in a logical unit that can be accessed through only one access point, one variable.

We could make use of this technique when we want to provide some functionalities or group content in a manner to avoid polluting the application's global scope. It is very useful for creating components as well since it increases the readability and maintainability of our code.

๐Ÿ“œ Implementation

In practice, a singleton could be as simple as an object:

const MyNamespaceSingleton= {
   attribute1: 'value1',
   attribute2: 17,
   method1: function(){
   },
   method2: function(){
   },
   // More definitions...
}

This way we can easily call any method we defined using MyNamespaceSingleton.method1(), for example. Simple? Yeah. Good enough? It depends.

In fact, for namespacing, this simple implementation would be enough in most cases. However, it being just a simple object declaration, as you may have noticed, it carries some very known drawbacks.

If we plan to use this technique thinking about component isolation, this approach may not be suitable, because we end up with some common problems. First, all singleton attributes are publicly exposed and anytime we have the ability to override any of its attributes or methods. Second, thinking about components, we may need the ability to encapsulate things, defining what we want to keep private and what we really want to expose.

So, now you might be thinking what do we have to do to overcome these two issues, right?

Observing the previous namespace implementation, one can see how we can expose attributes and methods publicly (achieved by simply declaring them). Assuming that you know what scopes are (If you don't, I will leave a nice link about it in the reference section), it sounds like a good idea to refactor our implementation to include some kind of "scoping" capability in it. Changing a bit of the implementation, we can achieve the same behavior as before, but now with an IIFE function that returns an object holding only the exposable attributes and methods.

const MyComponent = (function (){
   return {
      publicAttribute1: true,
      publicMethod1: function() {
      },
      // the rest of attributes and methods to be exposed ...
   }
)();

Now, you might be asking yourself, "Wait a minute, what about the private methods and attributes you have mentioned before?". To provide a private context to our singleton component, we can just simply declare the variables and methods we need at the scope of the function.

const MyComponent = (function (){
   const privateVariable = 7;
   const privateName = 'privateName';

   function privateMethod1(){
   }

   return {
      publicAttribute1: true,
      publicMethod1: function() {
         return privateMethod1();
      },
      // the rest of attributes and methods to be exposed ...
   }
)();

Now we finally achieved the proper behavior for the singleton to be used as a component since we were able to achieve the encapsulation level we wanted.

๐Ÿ‘ Known Benefits

The main benefit provided from the singleton pattern is the code organization. It helps to modularize code and provide useful resources under a specific context, improving readability and maintainability.

๐Ÿ‘Ž Known Drawbacks

The Singleton Pattern is not only about benefits, it also offers some drawbacks, as it has the potential of coupling things tightly by providing only a single point of access, making code harder to test in isolation. This happens basically because of the way a singleton violates the single responsibility principle, controlling its own instance and its functionalities.

โœ”๏ธ Conclusion

This article has presented one of the most common design patterns used in Javascript and its famous use cases. At the first moment, a simple implementation was provided, focused on namespacing use. Then, it was presented some implementation improvements to overcome some well-known drawbacks. In the end, it was talked about this pattern's main pros and cons.

๐Ÿ“– References


If you liked this article or are enjoying my blog until here and want to support my efforts, don't forget to share it with your friends and leave your impression about it! Any comments would be appreciated!

Thanks for the reading and happy coding! ๐Ÿ˜ƒ