简体   繁体   English

使用工厂搭建 singleton object

[英]Use factory to build singleton object

I'm trying to create some singleton object with a factory:我正在尝试用工厂创建一些 singleton object:

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.我想使用getInstance(boolean newInstance)方法生成一个新的 object 或重复使用现有的 singleton object。

if newInstance is true : I will generate a new singleton object如果newInstance 为真:我将生成一个新的 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.如果newInstance 为 false :如果 myObject 是 null,则生成一个新的并返回,或者如果 myObject 不是 null,则返回它。

And this getInstance(boolean newInstance) must be thread safe.并且这个getInstance(boolean newInstance)必须是线程安全的。 Any idea how?知道怎么做吗?

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. Singleton 的全部要点是在某个 class的程序中拥有单个实例。参数化工厂方法以获取新实例或先前实例不属于 Singleton 的定义。

Also, the best Singleton implementation is known as the Bill Pugh Singleton :此外,最好的 Singleton 实现被称为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. William Pugh 实现确保多线程安全和最佳性能,因为嵌套的 static class 仅在调用方法getInstance()时由 class 加载程序加载。 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).实际上,static 嵌套 class 只是外部 class 的 static 成员(在创建时间方面与 static 字段或 static 方法没有区别)。 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. static 成员仅在使用 class 时创建,因此由于无法使用构造函数创建BillPughSingleton实例,因此仅当通过getInstance()方法使用外部 class 时才会生成单个线程安全实例。

EDIT编辑

If what you're asking is something that either creates a new instance if this is null or returns/overrides the existing one.如果您要问的是创建一个新实例(如果这是 null)或返回/覆盖现有实例。 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.那么,你需要的不是singleton而是一个retriever class。另外你在设计的时候也要考虑到这个retriever class会不会在多线程的场景下使用。 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.使该字段volatile意味着该值不会缓存在 CPU 中,因此更改会立即对所有线程可见。 Making the method synchronized ensures that only one thread can enter it at the same time.使方法synchronized确保只有一个线程可以同时进入它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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