Clone Safe Singleton Object

Cloning is the concept of creating the exact same copy. Java provides multiple ways to create exact replica of an existing object such as copy constructor, method copying each field value into a new object or java.lang.Cloneable interface clone method. The clone method is preferred because it saves the overhead of copying all the existing values and assigning them to a new object. The clone method is defined in the Object class.

By default Object class clone method is protected, so the clone method will not be available to create multiple instances of the Singleton class, it will give the error "The method clone() from the type Object is not visible" But there might be a scenario where either Singleton class is implementing java.lang.Cloneable interface or extending superclass which implements java.lang.Cloneable interface, then multiple copies of Singleton class can be created.

package org.wesome.dsalgo.design.pattern.singleton;

import java.util.Objects;

public class Apple implements Cloneable {
    static Apple appleInstance;

    private Apple() {
        System.out.println("Apple default constructor");
    }

    public static Apple getAppleInstance() {
        System.out.println("Apple getAppleInstance");
        if (Objects.isNull(appleInstance)) {
            synchronized (Apple.class) {
                if (Objects.isNull(appleInstance)) {
                    appleInstance = new Apple();
                }
            }
        }
        return appleInstance;
    }

    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
package org.wesome.dsalgo.design.pattern.singleton;

public class SingletonClass {
    public static void main(String[] args) throws CloneNotSupportedException {
        Apple apple = Apple.getAppleInstance();
        System.out.println("apple = " + apple);
        Apple apple1 = (Apple) apple.clone();
        System.out.println("apple1 = " + apple1);
    }
}
plugins {
    id 'java'
    id "io.freefair.lombok" version "6.4.1"
}

group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}

test {
    useJUnitPlatform()
}

 

To prevent Singleton object to be cloned multiple times, an Exception can be thrown from the overridden clone method or the same instance can be returned as shown below.

package org.wesome.dsalgo.design.pattern.singleton;

import java.util.Objects;

public class Apple implements Cloneable {
    static Apple appleInstance;

    private Apple() {
        System.out.println("Apple default constructor");
    }

    public static Apple getAppleInstance() {
        System.out.println("Apple getAppleInstance");
        if (Objects.isNull(appleInstance)) {
            synchronized (Apple.class) {
                if (Objects.isNull(appleInstance)) {
                    appleInstance = new Apple();
                }
            }
        }
        return appleInstance;
    }
    /*  throw exception or call the getInstance method  */
    public Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("Object cannot be cloned.");
    }
}
package org.wesome.dsalgo.design.pattern.singleton;

public class SingletonClass {
    public static void main(String[] args) throws CloneNotSupportedException {
        Apple apple = Apple.getAppleInstance();
        System.out.println("apple = " + apple);
        Apple apple1 = (Apple) apple.clone();
        System.out.println("apple1 = " + apple1);
    }
}
plugins {
    id 'java'
    id "io.freefair.lombok" version "6.4.1"
}

group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}

test {
    useJUnitPlatform()
}

 

follow us on