Reputation:
Is it possible to have a singleton in a factory method? I have many domains using the factory method. How do I work around with this. Please help me with an example.
Upvotes: 4
Views: 18078
Reputation: 131
This example is not a formal Factory Pattern (GoF) but is still helpful if you use it like a Static Factory Method
abstract class Product {}
class ConcreteProduct extends Product{}
class ProductSupportFactory {
private static ProductSupportFactory instance = null;
private ConcreteProduct product = null;
static {
instance = new ProductSupportFactory();
}
private ProductSupportFactory() {
product = new ConcreteProduct(); //object initialization
}
public static ProductSupportFactory getInstance(){
return instance;
}
public ConcreteProduct getProduct() {
return product;
}
public void setProduct(ConcreteProduct product) {
this.product = product;
}
}
public class ProductConsumer {
public static void main(String args[]){ //client
ConcreteProduct uniqueInstance = ProductSupportFactory.getInstance().getProduct();
ConcreteProduct sharedInstance = ProductSupportFactory.getInstance().getProduct(); //same object hash
}
}
Upvotes: 0
Reputation: 2710
"...create an interface for objects that create instances of the Singleton class. This is essentially a combination of the Abstract Factory, Factory Method and Functor patterns in the GoF book."
/**
* An interface defining objects that can create Singleton
* instances.
*/
public interface SingletonFactoryFunctor {
/**
* @return An instance of the Singleton.
*/
public Singleton makeInstance();
}
Upvotes: 4
Reputation: 2560
In this example, I believe you would want to synchronize your getInstance() method to ensure two threads do not simultaneously enter it. Otherwise two threads can end up inside the block where the singleton is instantiated which is very problematic. The only issue with this solution is you pay a premium for the synchronization of the method every time getInstance() is called. Example:
public static synchronized Singleton getInstance()
{
// since whole method is synchronized only 1 thread can
// enter the following block ensuring only one instance
// is ever created. however we pay a synchronization
// penalty every time this method is called.
if(mInstance==null) {
mInstance=new Singleton();
}
return mInstance;
}
Alternatively you could also switch to use eager initialization of the singleton instance rather than lazy initialization if initializing is cheap which guarantees concurrency as well as not paying a synchronized penalty for invoking the getInstance() method. Example:
// no synchronization penalty, but penalty for eager init
private static Singleton mInstance = new Singleton();
public static Singleton getInstance()
{
return mInstance;
}
The most optimized approach is to use double-checked locking, something you need Java 1.5 or newer to use reliably due to differing implementations of the volatile keyword in 1.4 or older JVMs (please refer to "Head First Design Patterns" chapter 5 p.182 published by O'Reilly Media, Inc. -- that is where I first read about this.) Example:
private volatile static Singleton mInstance;
private Singleton(){}
public static Singleton getInstance()
{
if(mInstance==null) {
synchronized (Singleton.class) {
// only pay synchronization penalty once
if(mInstance==null){
mInstance=new Singleton();
}
}
}
return mInstance;
}
Upvotes: 6
Reputation: 12267
Singleton you can implement like:
public class Singleton {
private static Singleton mInstance;
private Singleton(){}
public static Singleton getInstance()
{
if(mInstance==null){
mInstance=new Singleton();
}
return mInstance;
}
}
This class you can return in every Factory methode you want, like mepcotterell described before.
Upvotes: 2
Reputation: 406125
You should call your Singleton getInstance()
method from the factory method. The getInstance()
logic should handle the details of returning the one instance of the Singleton.
Upvotes: 3