简体   繁体   中英

Use factory to build singleton object

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?

This is not how Singletons work. The whole point of a Singleton is to have a 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. 。参数化工厂方法以获取新实例或先前实例不属于 Singleton 的定义。

Also, the best Singleton implementation is known as the Bill Pugh Singleton :

public class BillPughSingleton {

    private BillPughSingleton() {}

    public static BillPughSingleton getInstance() {
        return SingletonHelper.INSTANCE;
    }

    private static class SingletonHelper {
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }
}

The William Pugh implementation ensures multi-thread safety and the best performances as the nested static class is loaded by the class loader only when the method getInstance() is invoked. In fact, a static nested class is simply a static member of the outer class (no difference from a static field or a static method in terms of creation time). The static member is created only when the class is used, so since no instances of the BillPughSingleton can be created with a constructor, a single thread-safe instance is generated only when the outer class is used via the getInstance() method.

EDIT

If what you're asking is something that either creates a new instance if this is null or returns/overrides the existing one. Then, what you need is not a singleton but a retriever class. Besides, you should also take into consideration in your design whether this retriever class will be used in multi-thread scenarios 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;
    }
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM