3

I have a class that will act as singleton.
This class will get a file as part of the constructor. After that the class is ready to go.
So currently I use the double-check-locking idiom and get an instance of the singleton via a static getInstance() i.e. the classic way.
My problem is that currently I do constantly:

MySingleton.getInstance(theFile);

And theFile is only needed in the first time the singleton is constructed. After that, i.e. once the singleton has been constructed I don't need to pass in the theFile.
How would I do that?
I thought to create a MySingleton.getInstance(); but still this would not work since the caller must call the MySingleton.getInstance(theFile); the first time to construct a valid class.
How can I design this better?

Jim
  • 17,102
  • 31
  • 115
  • 227

7 Answers7

9

Declare an init() method that handles initialization using the file.

Simplify getInstance() to return the instance, but throw an IllegalStateException if init() has not been called yet.

For example:

public class MySingleton {

    private MySingleton INSTANCE;

    // private constructor is best practice for a singleton 
    private MySingleton(File theFile) {
        // initialize class using "theFile"
    }

    public static void init(File theFile) {
        // if init previously called, throw IllegalStateException
        if (INSTANCE != null)
            throw new IllegalStateException();
        // initialize singleton 
        INSTANCE = new MySingleton(theFile);
    }

    public static MySingleton getInstance() {
        // if init hasn't been called yet, throw IllegalStateException
        if (INSTANCE == null)
            throw new IllegalStateException();
        return INSTANCE;
    }

    // rest of class
}

Note that although this is not threadsafe, race conditions would be few indeed, if any, as long as init() is called early as part of your server startup.

Bohemian
  • 365,064
  • 84
  • 522
  • 658
3

In a typical Dependency Injection environment, your file name would be a property to the singleton bean corresponding to this singleton class, with scope as singleton. Then you just inject this bean in any class that needs it.

If your program doesn't have a DI container, then this file name should either be an application level property obtained as a JVM argument / through some properties file or worst case, a constant in that singleton class. The clients shouldn't worry about the file that is used by this singleton class.

Vikdor
  • 22,825
  • 9
  • 55
  • 81
1

May be you can provide a method to initialize a singleton. You can define a static method called initialize() that takes in the file and creates a singleton object - on the app startup or at the appropriate place. There after, you can just use getInstance().

Sudhanshu Umalkar
  • 4,046
  • 1
  • 22
  • 33
0

You can simply have a getInstance() method which doesn't have a file parameter.

It will throw an exception if it's called before the other one, but this is ok, since in any case you can only avoid passing the file if you are already sure that the singleton was created before.

Petar Ivanov
  • 84,604
  • 7
  • 74
  • 90
0

An alternative to the init() method + exception,

Singleton::getInstance().load(myFile)

Just ensure this is done at startup / whatever.

jwalk
  • 1,091
  • 10
  • 24
0

An alternative approach first of all the singletone with parameter is not a singletone.

To solve this problem you have two options, first was described in linked above the second is to get the resource from inside.

The file usually is associated with path, you could access to that path from kind of property storage that you pass/set during application start.

Possible implementation of such mechanism:

public enum MySingleton {
 INSTANCE;

 private final File theFiel;

 private MySingleton() {
   this.theFile = initialize(MySystemProperties.getValue(MySystemProperties.MY_SINGLETONE_PATH);

 }

 private File initialize(String path) { 
    reutrn new File(path); //

 }

}
Community
  • 1
  • 1
0

The only way to optimize it is by NOT using the singleton pattern at all.

Seriously. You're shooting yourself in the foot.

Whenever you start passing unused values to methods there should be really loud alarm bells going off, alerting you that something is architecturally rotten in the state of Denmark. Obviously you can choose to ignore those alarm bells (and most probably this answer too) but it doesn't make your code suck less. I know, I'm being a meanie here. But it's a simple matter of fact that using singletons will turn your programs to big piles of steaming spaghettizzle.

There are | huge amounts | of posts | on why | singletons suck | more ass | than a | leech on | a donkey.

Since I have no idea what exactly you want to achieve with that class I unfortunately can't offer a solution.

Except this: don't use a singleton.

You'll thank me later on. It will look hard and it will take a fair amount of reading and experimenting, but coding it right will make you feel so much better. And will turn you into a better programmer.

Community
  • 1
  • 1
Creynders
  • 4,442
  • 18
  • 21