【问题标题】:Singleton class with parameter带参数的单例类
【发布时间】:2013-02-19 16:59:57
【问题描述】:

我正在开发计算机视觉应用程序,我需要分类器类。此类在每次运行应用程序时都是不可变的,它会在初始化时从磁盘加载经过训练的数据。我想确保整个程序都可以访问相同的训练数据,并且我想在加载后阻止从磁盘重新加载。

我考虑的是使用静态类或单例。我不确定如何将数据加载到静态类,因为在编译时不知道数据文件的路径 - 这将是程序参数。所以我在想单例模式,但是我不知道如何动态初始化它。

我的想法是使用以下内容:

class Singleton {
    private static Singleton instance;
    private Singleton() { ... }
    private static SomeDataObject data;

    public static Singleton getInstance() {
        if(instance == null)
            instance = new Singleton();

            return instance;
    }

    public static init(string dataPath){
        if(data == null)
             loadDataFromFile(dataPath)
    }
}

行不通,因为我无法控制首先调用哪个方法。

我知道正确的方法是在开始时使用数据创建实例并将其传递给所有需要它的类和方法,但这并不是真正的通用解决方案。我可以在自己的代码中跟踪对 Classifier 的所有调用,但如果我将代码作为 API,这将是一个问题。

简而言之如何在运行时初始化单例?

【问题讨论】:

  • 程序参数dataPath如何以编程方式访问?
  • 您不需要both 静态单例实例 数据对象。此外,您当前的单例实现不是线程安全的。
  • @MattBall 它可以来自 GUI,也可以来自命令行参数
  • 首先,你需要确定你需要使用单例模式。当您需要 > 确保只创建一个类的一个实例时,应使用单例。 提供对对象的全局访问点。 oodesign.com/singleton-pattern.html 看来你不需要Singleton。全局变量不好,单例也是。
  • @bancer 我需要 SomeDataObject 的单个实例可访问,并且该实例应该可由多种其他类型的分类器访问,而不需要共享某些父类。

标签: java oop singleton design-patterns


【解决方案1】:

我不认为(确切地说)你想做的事情会奏效。

以下方法可行:

public static void main(String[] args)
{
  Singleton.init("somepath");
  ...
  Singleton.getInstance().doingStuff();
  ...
}

更好的实现可能是:(如果您尝试使用它而不首先调用init,这将导致NullPointerException)(虽然不再是真正的Singleton)

private static Singleton instance;
private SomeDataObject data;

private Singleton(String path) { loadDataFromFile(path); ... }

public static Singleton getInstance() {
   return instance;
}

public static void init(String dataPath){
   instance = new Singleton(dataPath);
}

然后是:(除了可能的不良编码习惯)

class Main
{
  public static void main(String[] args)
  {
    Singleton.currentPath = "somepath";
    ...
  }
}

class Singleton
{
  public static String currentPath = null;
  private static Singleton instance;
  private SomeDataObject data;

  private Singleton(String path) { loadDataFromFile(path); ... }

  public static Singleton getInstance() {
     if(instance == null && currentPath != null)
        instance = new Singleton(currentPath);
     return instance;
  }
}

我想这并不能真正解决问题。

【讨论】:

  • 但我也可以做 Singleton.getInstance().doStuff() ,那将是错误的,因为没有进行初始化。正如我在帖子中所说,在我的代码中我可以跟踪这一点,但总的来说这并不能解决任何问题。
  • @jnovacho 您可以让构造函数读取存储在其他地方的静态变量,但我想这基本上是相同的问题。我认为你不能比我在答案中提供的更好(除非你想在每次调用时将路径传递给getInstance)。
  • 对我来说,第一个使用 public static void init()
【解决方案2】:

我使用的东西比当前获胜的解决方案“更”线程安全,几乎没有使用同步。

import java.util.function.Supplier;

public class InitOnce {

/**
 * Marked as final to prevent JIT reordering
 */
private final Supplier<String> theArgs;

private InitOnce(Supplier<String> supplier) {
    super();
    this.theArgs = supplier;
}

/**
 * Uses the arguments to do something
 * 
 * @return
 */
public String doSomething() {
    return "Something : " + theArgs.get();
}

/**
 * Initializes all the things
 * 
 * @param someArgs
 */
public static synchronized void init(final Supplier<String> someArgs) {
    class InitOnceFactory implements Supplier<InitOnce> {
        private final InitOnce initOnceInstance = new InitOnce(someArgs);

        @Override
        public InitOnce get() {
            return initOnceInstance;
        }
    }

    if (!InitOnceFactory.class.isInstance(instance)) {
        instance = new InitOnceFactory();
    } else {
        throw new IllegalStateException("Already Initialized");
    }
}

private static Supplier<InitOnce> instance = new InitOnceHolder();

/**
 * Temp Placeholder supplier
 * 
 */
private static final class InitOnceHolder implements Supplier<InitOnce> {
    @Override
    public synchronized InitOnce get() {

        if (InitOnceHolder.class.isInstance(instance))
            throw new IllegalStateException("Not Initialized");

        return instance.get();
    }

}

/**
 * Returns the instance
 * 
 * @return
 */
public static final InitOnce getInstance() {
    return instance.get();
}
}

【讨论】:

    猜你喜欢
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-16
    • 2020-09-20
    • 2010-11-06
    • 2020-06-19
    相关资源
    最近更新 更多