Reputation: 456
I'm trying to create some singleton object with a factory:
public class MyObjectFactory {
private MyObject myObject;
public MyObject getInstance(boolean newInstance) {
if (newInstance) {
// return new object
} else {
// return the old object
}
}
}
I want to use the getInstance(boolean newInstance) method to generate a new object or reuse the existing singleton object.
if newInstance is true: I will generate a new singleton object
if newInstance is false: if myObject is null, then generate a new one and return, or if myObject is not null, just return it.
And this getInstance(boolean newInstance) must be thread safe. Any idea how?
Upvotes: 0
Views: 126
Reputation: 6805
This is not how Singletons work. The whole point of a Singleton is to have a single instance across the program of a certain class. Parameterizing your factory method to either get a new instance or a previous one does not fall into the definition of a Singleton.
The best Singleton implementation is the Bill Pugh Singleton
:
public class BillPughSingleton {
// Private constructor to force the invocation of getInstance()
private BillPughSingleton() {}
public static BillPughSingleton getInstance() {
return SingletonHelper.INSTANCE;
}
private static class SingletonHelper {
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
}
The William Pugh Singleton ensures multi-thread safety and avoids eager creation, as it relies on a nested static class to create an instance. This implementation is useful when a class provides several services besides the retrieval of the single instance. In fact, if the member INSTANCE
was declared at class-level of the outer class, the invocation of any method of the class would cause an eager initialization of INSTANCE
. Instead, with a nested static class, the static member INSTANCE
is initialized only when the nested class is loaded, i.e. when the method getInstance()
is invoked, initializing INSTANCE
only on demand and making also the initialization thread-safe.
In your case, if the only purpose of your class is to create and return a single instance, you can use a simpler implementation:
public class SimplerSingleton {
private static SimplerSingleton INSTANCE = new SimplerSingleton();
// Private constructor to force the invocation of getInstance()
private SimplerSingleton() {}
public static SimplerSingleton getInstance() {
return INSTANCE;
}
}
If what you're asking is something that either creates a new instance when null or returns/overrides the existing one. Then, what you need is not a singleton, but a retriever class (you should also consider whether it will be used in a multi-thread scenario or not). Here is a basic implementation:
class MyRetriever {
private static MyClass instance;
//Private constructor to force the factory method invocation
private MyRetriever() {}
//Synchronizing the method in order to avoid race condition and establish a happens-before relationship between threads
public synchronized static MyClass getInstance(boolean flagOverride) {
if (flagOverride || instance == null){
instance = new MyClass();
}
return instance;
}
}
Upvotes: 2
Reputation: 11934
According to your comment, this is one way to implement what you want:
public class MyObjectFactory {
private volatile MyObject inst;
public synchronized MyObject getInstance(boolean newInstance) {
if(newInstance) {
inst = new MyObject(...);
}
return inst;
}
}
Making the field volatile
means that the value is not cached in the CPU, so changes are immediately visible to all threads. Making the method synchronized
ensures that only one thread can enter it at the same time.
Upvotes: 1