Other Ways of Singleton in Java

Other Ways of Singleton in Java

No, it is not. You didn't declare myClass private static final, nor the getInstance() is static. The code also doesn't really compile.

Here's the Singleton idiom:

public class MyClass {
private static final MyClass myClass = new MyClass();

private MyClass() {}

public static MyClass getInstance() {
return myClass;
}
}

It should be private, so that nobody else can access it directly. It should be static so that there's only one of it. It should be final so that it cannot be reassigned. You also need to instantiate it directly during declaration so that you don't need to worry (that much) about threading.

If the loading is expensive and you thus rather prefer lazy loading of the Singleton, then consider the Singleton holder idiom which does initialization on demand instead of during classloading:

public class MyClass {
private MyClass() {}

private static class LazyHolder {
private static final MyClass myClass = new MyClass();
}

public static MyClass getInstance() {
return LazyHolder.myClass;
}
}

You should however put big question marks whether you need a Singleton or not. Often it's not needed. Just a static variable, an enum, a factory class and/or dependency injection is often the better choice.

cracking singleton with other ways

Three ways I can think of are:

Serialization

If your singleton class is serializable, then you could serialize an instance of it, and deserialize it back and get a second object of that class.

You could avoid this by implementing readResolve method.

public class Singleton implements Serializable {
private static final Singleton INSTANCE = new Singleton();

public static Singleton getInstance(){
return INSTANCE;
}

public Object readResolve() throws ObjectStreamException {
return INSTANCE; //ensure singleton is returned upon deserialization.
}
}

Class Loading

The same class could be loaded by two different class loaders, as such, you could create two instances of your singleton class by simply invoking its getInstance method in a class loaded by two different class loaders. This approach would work without having to resort to violating the private constructor.

ClassLoader cl1 = new URLClassLoader(new URL[]{"singleton.jar"}, null);
ClassLoader cl2 = new URLClassLoader(new URL[]{"singleton.jar"}, null);
Class<?> singClass1 = cl1.loadClass("hacking.Singleton");
Class<?> singClass2 = cl2.loadClass("hacking.Singleton");
//...
Method getInstance1 = singClass1.getDeclaredMethod("getInstance", ...);
Method getInstance2 = singClass2.getDeclaredMethod("getInstance", ...);
//...
Object singleton1 = getInstance1.invoke(null);
Object singleton2 = getInstance2.invoke(null);

Reflection

As you have well pointed out, via reflection you could create two instances of the class. I think the previous examples was just a variant of the same approach. But I believe you could prevent these two from happening using a SecurityManager.

System.setSecurityManager(new SecurityManager());

What is an efficient way to implement a singleton pattern in Java?

Use an enum:

public enum Foo {
INSTANCE;
}

Joshua Bloch explained this approach in his Effective Java Reloaded talk at Google I/O 2008: link to video. Also see slides 30-32 of his presentation (effective_java_reloaded.pdf):

The Right Way to Implement a Serializable Singleton

public enum Elvis {
INSTANCE;
private final String[] favoriteSongs =
{ "Hound Dog", "Heartbreak Hotel" };
public void printFavorites() {
System.out.println(Arrays.toString(favoriteSongs));
}
}

Edit: An online portion of "Effective Java" says:

"This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton."

What's Alternative to Singleton

The Google Testing blog has a series of entries about avoiding Singleton (in order to create testable code). Maybe this can help you:

  • Using dependency injection to avoid singletons
  • Singletons are Pathological Liars
  • Root Cause of Singletons
  • Where have all the Singletons Gone?

The last article explains in detail how to move the creation of new objects into a factory, so you can avoid using singletons. Worth reading for sure.

In short we move all of the new operators to a factory.
We group all of the objects of similar lifetime into a single factory.

Different ways to write singleton in Java

The difference between your code and the "sample code" is that your singleton is instantiated when the class is loaded, while in the "sample" version, it is not instantiated until it is actually needed.

Singleton's other members

One note is that it is important to distinguish between the concept of a singleton (a class/object that has only a single instance) and the design pattern which achieves this via a class holding a single static instance of itself accessible in the global static name space. The concept of a singleton is frequently used in designs, the implementation of it via the singleton design pattern, however, is often frowned upon.

In the below, singleton is used to refer to the specific design pattern.

Part 1

  1. A Singleton's members do not need to be static, and usually are not.
  2. See 1.
  3. A singleton (design pattern) requires an instance to itself in order to return that instance to users of the singleton, as well as keeping a reference to itself active to avoid garbage collection (as you suggest). Without this single instance, the object is essentially not an implementation of the singleton design pattern. You can create a class for which you only create a single instance and pass this class around where it is required (avoiding the global static namespace), and this would essentially be a recommended way to avoid using the singleton pattern.

Part 2:

Sharing your thread pools is probably wise (but depends on your requirements), and this can be done in a number of ways. One way would be to create a single pool and to pass this pool (inject it) into the classes that require it. Usual recommendation for this is to use something like Spring to handle this for you.

Using a singleton is also an option, but even if your thread pool here is encapsulated in a singleton, it is still generally preferable to inject this singleton (preferably referenced via an interface) into dependent objects (either via a setter or in their constructor) instead of having your objects refer to the singleton statically. There are various reasons for this, with testing, flexibility, and control over order of instantiation being some examples.

When using the singleton design pattern, do other methods need to use synchronized keyword to ensure thread safety?

First, a Singleton pattern is best implemented as Enum in Java
Second, each email manipulation function (clear, Recycle, delete) should be synchronized to ensure thread safety (the link is about an Enum, but the same holds about each and every Sinlgeton implementation):

public synchronized void RecycleEmail(Email email)


Related Topics



Leave a reply



Submit