On the use of Singletons

Singleton is a tempting pattern to use because it simplifies the coding and I am a big fan of simplification. But remember there is an assumption that there indeed will be only one instance of the class for which you are creating a singleton. But what if later on we find out that no longer needs to be true? Its then that Singleton backfires in a big way and creates a major refactoring job for us. Wouldn’t it be better if we opt for the general solution where we design the system so that multiple instances of a class are possible, but if one wants, they can use a single instance. The biggest temptation I have found for Singleton is that it avoids us to have to pass references around everywhere in the code. E.g., consider some class foo:

class foo {
  public foo(A a, B b, C c) {

  }
}

Let’s say foo will have to do some initialization that depends on the application config. Without the Singleton pattern, its ugly to have to pass this config around all the time whenever we want to create a foo:

public foo(Config config, A a, B b, C c) {

  }

It creates too much noise and is ugly to read. Also consider the recursive effect. Say you want to create foo from a class that is not the top-level class in the program. Now that class needs to have instance of Config passed to it and so on. To add, suppose there are some more parameters like config which are the same for all instances of foo. You can imagine the code getting very ugly. With Singleton, the code gets much simplified:

public foo(A a, B b, C c) {
  Config.INSTANCE.getWhatever();
}

But what if the system evolves so that the class that we have singleton-ized is no longer singular and we want to be able to create multiple instances of it? It may seem like an unlikely sceanrio never to occur but who knows about the future? As the saying goes we should hope for the best but prepare for the worst. Is there a way we can avoid singleton-izing the class but still keep the code clean? There is. We use inner classes:

class FooFactory {

  public FooFactory(Config config) {
      this.config = config;
  }

  public foo createFoo(A a, B b, C c) {
      return new foo(a, b, c)
  }

  class foo {
      public foo(A a, B b, C c) {
          FooFactory.this.config.getWhatever();
      }
  }
}

Now we can use it like this from the main application. First create a FooFactory – a one-time activity in ctor of your top-level class for example:

fooFactory = new FooFactory(config);

Then whever you want a foo:

  fooFactory.createFoo(a, b, c);

The ugliness of having to pass config around everywhere is gone and we have avoided using Singleton as well. With C# you can even keep the foo and FooFactory in separate files but alas you cannot do it in Java [1] – another reason to avoid Java if you can.

This entry was posted in Computers, programming, Software and tagged , . Bookmark the permalink.

Leave a comment