Monday, March 10, 2008

Singleton Pattern

"Singleton Pattern" is used to restrict the instantiation of a class to exactly one object. In this tutorial we will learn how to create a singleton class in java, the problems associated with different instantiation methods and how to solve them.

Simple Form

Here is the simple form of a Singleton Class

public class Singleton{

// an instance is created during startup.
private static Singleton instance = new Singleton();

// private constructor disables creating an object of instance Singleton
private Singleton(){
}

public static Singleton getInstance(){
return instance;
}
}
This is the simplest form of Singleton. An instance is created when the class is loaded.

Test it

Invoke the getInstance() class twice and check whether the returned instances are same.
Here is the Junit test class.


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;


/**
* Unit test for Singleton Class
*/
public class SingletonTest{

@Test
public void checkReference(){

Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();

assertEquals( s1 , s2 );
System.out.println("Reference Test completed" );
}

@Test
public void checkEquals(){

Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();

assertTrue( s1.equals(s2) );

System.out.println("Equality Test completed" );
}
}

This test checks the reference and equality of the returned singleton classes. As you expect the Singleton class passes both tests successfully.

Startup Time

The only issue is, static loading increases the startup time, when the singleton class takes a long time to initialize or there are a large number of classes to initialize.


Lazy Loading
The Alternative is to lazy load the Singleton. In this case, the singleton class is not initialized until getInstance() method is invoked.



/**
* LazySingleton Description.
*/
public class LazySingleton {

private static LazySingleton instance = null;

private LazySingleton(){
}

public static LazySingleton getInstance(){
if( instance == null ){
instance = new LazySingleton();
}
}
}
This class is not loaded during startup, but initialized the first time getInstance() method is invoked.

Test It

Change the test case to test LazySingleton


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;


/**
* Unit test for Singleton Class
*/
public class LazySingletonTest{

@Test
public void checkReference(){

LazySingleton s1 = LazySingleton.getInstance();
LazySingleton s2 = LazySingleton.getInstance();

assertEquals( s1 , s2 );
System.out.println("Reference Test completed" );
}

@Test
public void checkEquals(){

LazySingleton s1 = LazySingleton.getInstance();
LazySingleton s2 = LazySingleton.getInstance();

assertTrue( s1.equals(s2) );

System.out.println("Equality Test completed" );
}
}
When you run the tests you notice that, all tests pass successfully. The reason is that test invokes getInstance() sequentially, and it gets initialized only once.

What if multiple threads invoke getInstance() simultaneously?

Threads

No comments: