在Java中使用带参数的单例 [英] Singleton with Arguments in Java

查看:551
本文介绍了在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).
    }
}

正如你所看到的,即使在这里我也有问题在传递第一个文件路径后,传递不同的文件路径意味着什么。这就是为什么我喜欢在答案中发布商店的想法。无论如何,我想将这个逻辑抽象为Singleton类,而不是包含在run方法中加载文件的逻辑。我不会提供另一个例子,但我希望你能得到这个想法。请让我听听你的想法,以更优雅的方式来完成我想要做的事情。再次感谢你!

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!

推荐答案

我会非常明确地指出:带参数的单身人士不是单身人士/ strong>。

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

如果单例执行的操作是重复的,并且使用不同的参数每次,您都可以将参数传递给正在执行的main方法:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆