使用工厂构建单例对象

问题描述 投票:0回答:2

我正在尝试用工厂创建一些单例对象:

public class MyObjectFactory {
    private MyObject myObject;

    public MyObject getInstance(boolean newInstance) {
        if (newInstance) {
            // return new object
        } else {
            // return the old object
        }
    }
}

我想使用 getInstance(boolean newInstance) 方法生成新对象或重用现有的单例对象。

if newInstance 为 true:我将生成一个新的单例对象

if newInstance is false:如果 myObject 为 null,则生成一个新实例并返回,如果 myObject 不为 null,则返回它。

并且这个 getInstance(boolean newInstance) 必须是线程安全的。知道怎么做吗?

java thread-safety singleton
2个回答
1
投票

根据您的评论,这是实现您想要的内容的一种方法:

public class MyObjectFactory {
   private volatile MyObject inst;
   public synchronized MyObject getInstance(boolean newInstance) {
     if(newInstance) {
       inst = new MyObject(...);
     }
     return inst;
   }
}

使该字段为

volatile
意味着该值不会缓存在CPU中,因此所有线程都会立即看到更改。制作方法
synchronized
确保只有一个线程可以同时进入。


1
投票

这不是单例的工作方式。 Singleton 的全部要点是在整个程序中拥有某个类的“单个实例”。参数化工厂方法以获取新实例或前一个实例不属于单例的定义。 最好的单例实现是

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();
    }
}

William Pugh Singleton 确保多线程安全并避免急切创建,因为它依赖于嵌套静态类来创建实例。当一个类除了检索单个实例之外还提供多种服务时,此实现非常有用。事实上,如果成员 
INSTANCE

是在外部类的类级别声明的,则调用该类的

any
方法将导致 INSTANCE 的急切初始化。相反,对于嵌套静态类,静态成员
INSTANCE
仅在加载嵌套类时初始化,即当调用方法
getInstance()
时,仅根据需要初始化
INSTANCE
并使初始化线程安全。
在您的情况下,如果您的类的唯一目的是创建并返回单个实例,您可以使用更简单的实现:

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; } }

编辑

如果您要求的是在 null 时创建一个新实例或返回/覆盖现有实例。那么,你需要的不是单例,而是检索器类(你还应该考虑是否会在多线程场景中使用)。这是一个基本的实现:

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; } }

© www.soinside.com 2019 - 2024. All rights reserved.