Skip to content

Singleton Pattern in Java, with Examples

Learn the Singleton design pattern in Java: a software engineering pattern that limits the creation of objects of a class to one, with code examples.

You can download the project for this post by clicking HERE.

In this tutorial we are going to talk about the "Singleton" design pattern, which in software engineering is a pattern designed to limit the creation of objects belonging to a class. The goal of this pattern is to guarantee that a class has only one instance and to provide a global point of access to it. This pattern, for example, is often used for database connections.

This pattern is implemented by making the class constructor private and creating (in the class itself) a method that creates an instance of the object if it doesn't exist yet. Let's look at an example of this pattern in which we are going to create a class called "SoyUnico" ("I am unique") with a private constructor and a method called 'getSingletonInstance()' that will be in charge of creating an instance of this class if it hasn't been created yet:

public class SoyUnico {

    private String nombre;
    private static SoyUnico soyUnico;

    // The constructor is private, so a default constructor can't be generated.
    private SoyUnico(String nombre) {
        this.nombre = nombre;
        System.out.println("Mi nombre es: " + this.nombre);
    }

    public static SoyUnico getSingletonInstance(String nombre) {
        if (soyUnico == null){
            soyUnico = new SoyUnico(nombre);
        }
        else{
            System.out.println("No se puede crear el objeto "+ nombre + " porque ya existe un objeto de la clase SoyUnico");
        }
        
        return soyUnico;
    }
    
    // getter and setter methods

}

We can see that when we call the 'getSingletonInstance()' method, it checks whether the 'soyUnico' attribute is null or not, and if it is, it creates the object. If the object has already been created, it will print a message to the screen telling us that an object of that class already exists.

Let's see that it really creates only one object by running the following code, in which we call the 'getSingletonInstance()' method twice:

public class Main {

    public static void main(String[] args) {
        
        SoyUnico ricardo = SoyUnico.getSingletonInstance("Ricardo Moya");
        SoyUnico ramon = SoyUnico.getSingletonInstance("Ramón Invarato");
        
        // ricardo and ramon are references to a single object of the SoyUnico class
        System.out.println(ramon.getNombre());
        System.out.println(ricardo.getNombre());   
    }
}

The output of this code is the following:


Mi nombre es: Ricardo Moya
No se puede crear el objeto Ramón Invarato porque ya existe un objeto de la clase SoyUnico
Ricardo Moya
Ricardo Moya

We can see that when there is no object of the class "SoyUnico", it creates one, and if we try to create it again, the method tells us that there is already one but assigns us a reference to that object. That is, the variables 'ricardo' and 'ramon' reference the same, single object of the class "SoyUnico", as we can see when we ask for the 'nombre' attribute of the class.

Finally, this pattern wouldn't be perfectly implemented if we didn't control copying (or cloning) of objects of this class. That's why it's important to override the 'clone()' method, so that when someone tries to clone this object, an exception is thrown. We override this method as follows:

//We override the clone method so an object of this class can't be cloned
@Override
public SoyUnico clone(){
    try {
        throw new CloneNotSupportedException();
    } catch (CloneNotSupportedException ex) {
        System.out.println("No se puede clonar un objeto de la clase SoyUnico");
    }
    return null; 
}

Let's see what happens if we try to clone the object of the class "SoyUnico":

public class Main {

    public static void main(String[] args) {
        
        SoyUnico ricardo = SoyUnico.getSingletonInstance("Ricardo Moya");

        try{
            SoyUnico richard = ricardo.clone();
            System.out.println(richard.getNombre());
        }catch (NullPointerException ex){
            ex.printStackTrace();
        }
    }
}

We can see that it throws an exception and doesn't let us clone that object.


Mi nombre es: Ricardo Moya
No se puede clonar un objeto de la clase SoyUnico
java.lang.NullPointerException
	at Main.Main.main(Main.java:21)

In summary, in this tutorial we have given a very simple example to see how the "Singleton" pattern works. It is a very widely used design pattern (perhaps the most used), applicable in cases where we only want a single object of the class we implement.

“Singleton Pattern in Java, with Examples” by Ricardo Moya at jarroba.com, licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0. Registered at Safe Creative.

Ricardo Moya

I work in Machine Learning and Big Data. I like learning new technologies and explaining them as clearly as I can on this site.

You may also like

Comments

Leave a comment


This site uses Akismet to reduce spam. Learn how your comment data is processed.