Question

I don't want to use singleton, but I simply cannot allow more than one instance of my class.

Would you consider this a good approach, and if not, what's a better way?

public class SoundSystem {

    private static boolean instanceCreated = false;

    public SoundSystem() {
        if(instanceCreated) {
            throw new IllegalStateException("Only one instance can be created.");
        }

        instanceCreated = true;
    }
}
Was it helpful?

Solution

This is a singleton, even if you are not enforcing it in the "traditional" manner. I don't recommend this approach, and I think you should find another way.

For example, why not create a single SoundSystem instance when your program starts? You don't need to explicitly enforce its single-ness, just pass that instance along to other objects that need access to the sound system. As a bonus, this also lets you easily drop in support for different types of SoundSystems if you need it some day (a nice little extra benefit, even if you don't need this).

On top of all this, will the OpanAL initialization itself fail if you try and initialize multiple SoundSystems? If not, then there's not really a reason to place an artificial limit. If so, then you can just let OpanAL determine what is and isn't an error. But in any case, it wouldn't be a risk if you simply just create one instance and pass it off instead of letting all your application classes query the instance themselves.

Be careful you don't fall into the XY Problem trap here. Singletons aren't inherently evil, but for some reason they are frequently misused, hence the general advice against them. There is usually a cleaner way, and these cleaner ways usually come with a lot of bonus added benefit. Think about the actual problem you are trying to solve / situation you are trying to avoid here.

OTHER TIPS

No, it's not a good approach.

Let's take a quick example in a context of multi-threading.

Thread 1 instantiates SoundSystem, the if(instanceCreated) returns false, before changing instanceCreated to true the scheduler interrupts Thread 1. Now Thread 2 can also instantiates SoundSystem since isInstanceCreated is false at that time.

But at the end, both thread will have a different instance.

You can use an enum, if you are willing to make all of your fields final. This too has some "code smell" to it though. It will protect against multi-threaded issues, but does have the restriction that all of your SoundSystem instance variables would need to be final.

public enum SoundSystem {
    INSTANCE("Hello", "World");

    private final Object field1;
    private final Object field2;

    private SoundSystem(Object field1, Object field2) {
        this.field1 = field1;
        this.field2 = field2;
    }

    @Override
    public String toString() {
        return field1.toString() + "  " + field2.toString();
    }

    public Object getField1() {
        return this.field1;
    }

    public Object getField2() { 
        return this.field2;
    }

    //etc., etc.
}

You can then use SoundSystem.INSTANCE to gain access to your singleton item

The solution you posted allows a garden variety "race-condition". Two entities trying to create a your SoundSystem at the same time could end up both creating an instance.

Maybe making all the methods of and variables of SoundSystem static will get you what you desire, but it is hard to know without more information.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top