BAEL-4933 | Differences between static classes and the singleton pattern in Java (#11014)
* BAEL-4220 | A Guide to IllegalAccessError and when it happens * BAEL-4220 | A Guide to IllegalAccessError and when it happens | fix tests * BAEL-4220 | A Guide to IllegalAccessError and when it happens | fix tests * BAEL-4220 | A Guide to IllegalAccessError and when it happens | BDD test names * BAEL-4494 | .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])? * BAEL-4494 | .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])? * BAEL-4933 | Differences between static classes and the singleton pattern in Java Co-authored-by: root <anmoldeep0123@gmail.com>
This commit is contained in:
parent
1910561a54
commit
37db34cb8a
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.staticsingletondifference;
|
||||||
|
|
||||||
|
public class CachingSingleton implements SingletonInterface {
|
||||||
|
|
||||||
|
private CachingSingleton() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder {
|
||||||
|
public static final CachingSingleton instance = new CachingSingleton();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CachingSingleton getInstance() {
|
||||||
|
return SingletonHolder.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String describeMe() {
|
||||||
|
return "Caching Responsibilities";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String passOnLocks(MyLock lock) {
|
||||||
|
return lock.takeLock(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void increment() {
|
||||||
|
throw new UnsupportedOperationException("Not Supported Here");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.baeldung.staticsingletondifference;
|
||||||
|
|
||||||
|
public class FileSystemSingleton implements SingletonInterface{
|
||||||
|
|
||||||
|
private int filesWritten;
|
||||||
|
|
||||||
|
private FileSystemSingleton() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder {
|
||||||
|
public static final FileSystemSingleton instance = new FileSystemSingleton();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FileSystemSingleton getInstance() {
|
||||||
|
return SingletonHolder.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String describeMe() {
|
||||||
|
return "File System Responsibilities";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String passOnLocks(MyLock lock) {
|
||||||
|
return lock.takeLock(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void increment() {
|
||||||
|
this.filesWritten++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFilesWritten() {
|
||||||
|
return filesWritten;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.staticsingletondifference;
|
||||||
|
|
||||||
|
public class MyLock {
|
||||||
|
|
||||||
|
protected String takeLock(int locks) {
|
||||||
|
return "Taken Specific Lock";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.baeldung.staticsingletondifference;
|
||||||
|
|
||||||
|
import java.io.ObjectStreamException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class SerializableCloneableSingleton implements SingletonInterface, Serializable, Cloneable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -1917003064592196223L;
|
||||||
|
|
||||||
|
private int state;
|
||||||
|
|
||||||
|
private SerializableCloneableSingleton() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder {
|
||||||
|
public static final SerializableCloneableSingleton instance = new SerializableCloneableSingleton();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SerializableCloneableSingleton getInstance() {
|
||||||
|
return SingletonHolder.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String describeMe() {
|
||||||
|
throw new UnsupportedOperationException("Not Supported Here");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String passOnLocks(MyLock lock) {
|
||||||
|
throw new UnsupportedOperationException("Not Supported Here");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void increment() {
|
||||||
|
this.state++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object readResolve() throws ObjectStreamException {
|
||||||
|
return SingletonHolder.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object cloneObject() throws CloneNotSupportedException {
|
||||||
|
return this.clone();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.baeldung.staticsingletondifference;
|
||||||
|
|
||||||
|
public interface SingletonInterface {
|
||||||
|
|
||||||
|
public String describeMe();
|
||||||
|
|
||||||
|
public String passOnLocks(MyLock lock);
|
||||||
|
|
||||||
|
public void increment();
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.staticsingletondifference;
|
||||||
|
|
||||||
|
public class SingletonLock extends MyLock {
|
||||||
|
|
||||||
|
private SingletonLock() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder {
|
||||||
|
public static final SingletonLock instance = new SingletonLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SingletonLock getInstance() {
|
||||||
|
return SingletonHolder.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String takeLock(int locks) {
|
||||||
|
return "Taken Singleton Lock";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.staticsingletondifference;
|
||||||
|
|
||||||
|
public class SubUtility extends SuperUtility {
|
||||||
|
|
||||||
|
public static String echoIt(String data) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.staticsingletondifference;
|
||||||
|
|
||||||
|
public class SuperUtility {
|
||||||
|
|
||||||
|
public static String echoIt(String data) {
|
||||||
|
return "SUPER";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.baeldung.staticsingletondifference;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ForSingletonsUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStaticUtilClassInheritance_thenOverridingFails() {
|
||||||
|
SuperUtility superUtility = new SubUtility();
|
||||||
|
Assert.assertNotEquals("ECHO", superUtility.echoIt("ECHO"));
|
||||||
|
Assert.assertEquals("SUPER", superUtility.echoIt("ECHO"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSingletonDerivesBaseClass_thenRuntimePolymorphism() {
|
||||||
|
MyLock myLock = new MyLock();
|
||||||
|
Assert.assertEquals("Taken Specific Lock", myLock.takeLock(10));
|
||||||
|
myLock = SingletonLock.getInstance();
|
||||||
|
Assert.assertEquals("Taken Singleton Lock", myLock.takeLock(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSingletonImplementsInterface_thenRuntimePolymorphism() {
|
||||||
|
SingletonInterface singleton = FileSystemSingleton.getInstance();
|
||||||
|
Assert.assertEquals("File System Responsibilities", singleton.describeMe());
|
||||||
|
singleton = CachingSingleton.getInstance();
|
||||||
|
Assert.assertEquals("Caching Responsibilities", singleton.describeMe());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSingleton_thenPassAsArguments() {
|
||||||
|
SingletonInterface singleton = FileSystemSingleton.getInstance();
|
||||||
|
Assert.assertEquals("Taken Singleton Lock", singleton.passOnLocks(SingletonLock.getInstance()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSingleton_thenAllowState() {
|
||||||
|
SingletonInterface singleton = FileSystemSingleton.getInstance();
|
||||||
|
IntStream.range(0, 5)
|
||||||
|
.forEach(i -> singleton.increment());
|
||||||
|
Assert.assertEquals(5, ((FileSystemSingleton) singleton).getFilesWritten());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSingleton_thenAllowSerializationDeserialization() {
|
||||||
|
SingletonInterface singleton = SerializableCloneableSingleton.getInstance();
|
||||||
|
singleton.increment();
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
new ObjectOutputStream(baos).writeObject(singleton);
|
||||||
|
SerializableCloneableSingleton singletonNew = (SerializableCloneableSingleton) new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())).readObject();
|
||||||
|
Assert.assertEquals(1, singletonNew.getState());
|
||||||
|
Assert.assertEquals(singleton.hashCode(), singletonNew.hashCode());
|
||||||
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSingleton_thenAllowCloneable() {
|
||||||
|
SerializableCloneableSingleton singleton = SerializableCloneableSingleton.getInstance();
|
||||||
|
singleton.increment();
|
||||||
|
try {
|
||||||
|
Assert.assertEquals(2, ((SerializableCloneableSingleton) singleton.cloneObject()).getState());
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue