Java 中带参数的单例 [英] Singleton with Arguments in Java
问题描述
我正在阅读维基百科上的 Singleton 文章,发现了这个例子:
I was reading the Singleton article on Wikipedia and I came across this example:
public class Singleton {
// Private constructor prevents instantiation from other classes
private Singleton() {}
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
虽然我真的很喜欢这个 Singleton 的行为方式,但我不知道如何调整它以将参数合并到构造函数中.在 Java 中执行此操作的首选方法是什么?我需要做这样的事情吗?
While I really like the way this Singleton behaves, I can't see how to adapt it to incorporate arguments to the constructor. What is the preferred way to do this in Java? Would I have to do something like this?
public class Singleton
{
private static Singleton singleton = null;
private final int x;
private Singleton(int x) {
this.x = x;
}
public synchronized static Singleton getInstance(int x) {
if(singleton == null) singleton = new Singleton(x);
return singleton;
}
}
谢谢!
我想我已经开始了一场争议风暴,因为我希望使用 Singleton.让我解释一下我的动机,希望有人能提出一个更好的主意.我正在使用网格计算框架并行执行任务.一般来说,我有这样的事情:
I think I have started a storm of controversy with my desire to use Singleton. Let me explain my motivation and hopefully someone can suggest a better idea. I am using a grid computing framework to execute tasks in parallel. In general, I have something like this:
// AbstractTask implements Serializable
public class Task extends AbstractTask
{
private final ReferenceToReallyBigObject object;
public Task(ReferenceToReallyBigObject object)
{
this.object = object;
}
public void run()
{
// Do some stuff with the object (which is immutable).
}
}
发生的情况是,即使我只是将数据的引用传递给所有任务,但当任务被序列化时,数据会一遍又一遍地复制.我想做的是在所有任务之间共享对象.当然,我可能会像这样修改类:
What happens is that even though I merely pass a reference to my data to all of the tasks, when the tasks are serialized, the data gets copied over and over. What I want to do is share the object among all of the tasks. Naturally, I might modify the class like so:
// AbstractTask implements Serializable
public class Task extends AbstractTask
{
private static ReferenceToReallyBigObject object = null;
private final String filePath;
public Task(String filePath)
{
this.filePath = filePath;
}
public void run()
{
synchronized(this)
{
if(object == null)
{
ObjectReader reader = new ObjectReader(filePath);
object = reader.read();
}
}
// Do some stuff with the object (which is immutable).
}
}
如您所见,即使在这里我也遇到了一个问题,即在传递第一个文件路径后,传递不同的文件路径没有任何意义.这就是为什么我喜欢在答案中发布的 store 的想法.无论如何,我不想在 run 方法中包含加载文件的逻辑,而是想将此逻辑抽象为一个 Singleton 类.我不会再提供另一个例子,但我希望你能明白.请让我听听您的想法,以更优雅的方式来完成我正在尝试做的事情.再次感谢!
As you can see, even here I have the issue that passing a different file path means nothing after the first one is passed. This is why I like the idea for a store which was posted in the answers. Anyhow, rather than including the logic for loading the file in the run method, I wanted to abstract this logic into a Singleton class. I will not provide yet another example, but I hope you get the idea. Please let me hear your ideas for a more elegant way to accomplish what I am trying to do. Thank you again!
推荐答案
我会非常清楚地说明我的观点:带参数的单例不是单例.
I'll make my point very clear: a singleton with parameters is not a singleton.
单例,顾名思义,就是一个你希望被实例化的对象不超过一次.如果您尝试向构造函数提供参数,那么单例的意义何在?
A singleton, by definition, is an object you want to be instantiated no more than once. If you are trying to feed parameters to the constructor, what is the point of the singleton?
您有两个选择.如果你想让你的单例用一些数据初始化,你可以在实例化之后加载数据,像这样:
You have two options. If you want your singleton to be initialized with some data, you may load it with data after instantiation, like so:
SingletonObj singleton = SingletonObj.getInstance();
singleton.init(paramA, paramB); // init the object with data
如果你的单例正在执行的操作是重复的,并且每次都有不同的参数,你不妨将参数传递给正在执行的主要方法:
If the operation your singleton is performing is recurring, and with different parameters every time, you might as well pass the parameters to the main method being executed:
SingletonObj singleton = SingletonObj.getInstance();
singleton.doSomething(paramA, paramB); // pass parameters on execution
无论如何,实例化总是无参数的.否则你的单身人士就不是单身人士.
In any case, instantiation will always be parameter-less. Otherwise your singleton is not a singleton.
这篇关于Java 中带参数的单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!