How popular OSS use patterns — Singleton

Prathamesh Mane
3 min readOct 24, 2022
Pattern

Patterns are everywhere, from nature to gigantic buildings, from mechanical systems to software. You know you don’t want to reinvent the wheel, so you look to Design Patterns: the lessons learned by those who’ve faced the same software design problems. As software engineers, we have considerable patterns across domains like micro-service patterns, workflow patterns, software integration patterns, etc. When I started coding, I was very much into (still I’m) “Head First design patterns” by Eric Freeman, and Elisabeth Robson. I would strongly recommend the book if you haven’t read it already. The book provides a practical demonstration of various patterns and the scenarios in which to use them. But nothing gets me excited when I see those patterns peeking out of the frameworks I use or through an open-source software I was diving through its source code.

This series is nothing but a verbal representation of that excitement. I will try to show you the various patterns being used in popular Open Source Software and how you can do the same within your application. So let’s jump directly to it.

Let’s focus on our first pattern — Singleton Pattern (One of a kind object). It is one of the object creation patterns that ensures only single instance of the class is created in the whole application and provides a global access point to it. To create a perfect singleton, we have to make sure —

  1. It’s thread-safe. Concurrent threads can access the instance without data corruption
  2. Serialization friendly — After deserializing the object, no new-instance should be created.
  3. Lazy loaded — If creation of singleton is costly, then it should be created only when accessed for first time.

The implementation we see a quite often is like below —

As you see the comments, you have to take care of multiple things, but even after that, it’s still not the perfect solution. The deserialization can create another object (to avoid this, we need to implement readResolve method), constructor visibility can be modified via reflections and new objects can be created without any runtime exception.

The best implementation is by using enum. And the same approach is used by “Spring Data Rest” project (The project eases developer’s life by automatically exposing your repositories as REST APIs. It’s a very well designed project which you can learn more of from project page).

The class we will see is org.springframework.data.rest.webmvc.spi.BackendIdConverter.DefaultIdConverter. Suppose you have entity class User, it will exposed at URI /users/{userId}. The textual representation of userId param is controlled by BackendIdConverter. One of it’s default implementation is DefaultIdConverter which does nothing but passes the #toString implementation as it is.

The above implementation is free from issues we discussed earlier because as per java specification,

  1. An enum type has no instances other than those defined by its enum constants. It is a compile-time error to attempt to explicitly instantiate an enum type. (Hence we only have one instance — INSTANCE).
  2. The final clone method in Enum ensures that enum constants can never be cloned.
  3. The special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization.
  4. Reflective instantiation of enum types is prohibited.

Together, these four things ensure that no instances of an enum type exist beyond those defined by the enum constants.

Today we saw one of the many interesting patterns OSS uses. In coming posts we will explore more interesting things like Outbox pattern, locator interface to name a few.

Till then you can read my previous posts on Event Driven architecture, workflow automation from link below. Happy reading.

--

--