This blog is no longer being maintained, please go to The missing link of Agile instead

Thursday, June 18, 2009

Design patterns in Scala: Singleton

I am always keen on improving my knowledge of Scala. Second thing is that I really enjoy to share what I learned with everyone (I do really hope people eventually gain much more interest in Scala :D). That's why I decided to make series on .. GoF design patterns in Scala.

For starters I've chosen our old friend - Singleton. Let's go then!

object Singleton

// Usage:
val singleton = Singleton

Done! Thx for reading..

..just kidding, let's dig a little deeper into that.

You are probably curious about thread safety of this solution. The actual code generated in bytecode and decompiled with JAD looks like that:

public final class Singleton$
implements ScalaObject
{

public Singleton$()
{
}

public int $tag()
throws RemoteException
{
return scala.ScalaObject.class.$tag(this);
}

public static final Singleton$ MODULE$ = this;

static
{
new Singleton$();
}
}

There are 3 things to consider:
  • Singleton object is initialized in static block so thread safety is guaranteed by JVM

  • Every time you reference Singleton object in your code, Scala compiler translates this call into 'Singleton$.MODULE$',

  • This implemention has also quite cool semantics of access modifiers (which is a bit more advanced topic; search for 'companion module' to learn more).

An important thing to notice is that Singleton is eagerly initialized so if you try:
java.lang.Class.forName("Singleton$")
it'll cause initialization to be performed. For now I have no idea how to force 'object' in Scala to be lazy initialized. The only solution I came up with would be:

// Incorrect (see the bottom of article)
class LazySingleton private () {
def apply() = this
}


// Correct
class LazySingleton private () {
}

object LazySingleton {
lazy val INSTANCE = new LazySingleton();
def apply() = INSTANCE
}

// Usage:
val singleton = Singleton()

The trick is to make default constructor private and have apply method of 'object' class type return the only instance of LazySingleton class.

Disadvantage of second implementation is a small but noticable difference in usage. First - requires '()' [apply[ operator to be used. Second - it returns different type of class depending on whether '()' is used (class LazySingleton) or not (object LazySingleton):

scala> C()
res1: C = C@304648

scala> C
res2: C.type = C$@1b9e7fc



Modified 2009-06-23: Previous implemention of lazy singleton was incorrect and led to wrong conclusions.

3 comments:

  1. Thanks for the post. I was looking for a solution and yours gave me this idea...
    Rename 'INSTANCE' to 'singleton' and the usage becomes an import statement. Then a 'var' is no longer needed.

    ReplyDelete
  2. Your information is more than 4 years outdated.

    ReplyDelete
  3. Considering the date article was written your argument is very solid

    ReplyDelete