Skip to main content
gamedev.net
🔒 Locked

[java] Singleton pattern in Java

Started by tebriel 24 replies 4.7k views
Original Post
tebriel
tebriel
Ok, say you have a thingy like the below code.

public class SingletonObject
{
    private SingletonObject()
    {
    }

    public static synchronized SingletonObject getSingletonObject()
    {
      if (ref == null)
          ref = new SingletonObject();
      return ref;
    }

    private static SingletonObject ref;
    //other stuff

    //Note this method -- esp. the static here
    public static void add(whateverObj whatever) {
      //do something
    }
}



It seems to me that there's two ways to use a class like this--only one is correct. SingletonObject.add(whatever); SingletonObject.getSingletonObject().add(whatever); Would it be correct to say that this part SHOULD NOT be static? public static void add(whateverObj whatever) Otherwise you can access the singleton object before it's instantiated. Without the static you can only call this: SingletonObject.getSingletonObject().add(whatever); Which should always be safe... Can anyone verify that this is all correct?
SumDude
SumDude
I'm pretty sure it's not supposed to be static.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                          
Looking for video game music? Check out some of my samples at http://www.youtube.c...ser/cminortunes            
                                                          
I'm currently looking to create music for a project, if you are inte
Saruman
Saruman
The method is not supposed to be static, that defeats the whole purpose of the pattern actually. You should be using the getSingletonObject()
Son of Cain
Son of Cain
Hi,

The add() method must not be static. Also, to ensure you really have a singleton, you could use a static inner class, like this:

public final class Singleton {  private static final class SingletonHolder {    private static final Singleton singleton = new Singleton();  }  private Singleton() {    // Singleton instantiation  }  private static final Singleton getInstance() {    return SingletonHolder.singleton;  }  public final void add(Object obj) {    // method of the Singleton  }}


However, you used a synchronized approach, so I'm not certain about how it should behave.

Son Of Cain

Edit: [ fixed the source tag ]
a.k.a javabeats at yahoo.ca
Funkapotamus
Funkapotamus
For games, do not use synchronized unless you feel very unsafe.
If you feel very unsafe, then you need to redesign in the first place :)

At any rate, remember that synchronized methods will KILL your fps if used at inopportune times. They're best left for server commands and other things that arn't FPS dependent.
BitMaster
BitMaster
Are you sure you need an instance of the singleton or are you doing that simply to say "I have implemented the Singleton Pattern"? Wouldn't a class with all static data and methods be enough?

Son of Cain: I'm not seeing any benefit to simply having a
private static final Singleton singleton = new Singleton();

in there. I'm not completely sure when inner classes are exactly loaded (when their container class is loaded or when they are first accessed?) but if the initialization time is important I'd rather set it to null during initialization and create it in getSingleton() or a more specific initialization method...
Son of Cain
Son of Cain
The use of inner classes to hold Singleton instances is only necessary when you have to ensure a Singleton is created outside the scope of the class providing the instance, but still in the same source file.

It is a bit intrinsic and very specific, but the inner class acts like a factory for the singleton instance. It is only interesting when you have an hierarchy of singletons, like: EquipmentFactory <- WeaponFactory, ArmorFactory, where all of them are singletons.

Son Of Cain
a.k.a javabeats at yahoo.ca
tebriel
tebriel
Quote:
Original post by BitMaster
Are you sure you need an instance of the singleton or are you doing that simply to say "I have implemented the Singleton Pattern"? Wouldn't a class with all static data and methods be enough?


Actually I had the same question myself earlier. I have a few guesses as to the answers, but rather than throwing stuff out I'll wait for someone more enlightened in Java to illustrate why this is better.

I suspect it has mostly to do with future changes: "if you decide that the class should no longer be a singleton, you may simply change the implementation of getInstance."
Son of Cain
Son of Cain
You use a Singleton because it is a good creational design pattern. Object instantiation should not be used at will, a very well designed app cares about the way its objects are instantiated. A singleton is a class that handles this instatiation, and is the only "point" of your application that can do this instantiation for you.

Singletons are used for "manager" classes, for example, a WindowManager, a PrinterManager, a DBConnectionPool, etc...

Hope it helped a bit =D

Son Of Cain
a.k.a javabeats at yahoo.ca
tebriel
tebriel
Found this, and if you're willing to read it, it definitely explains the entire subject in detail.

http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns_p.html

Basically there's two options, the more traditional way, and the "Java way", it seems. (not done reading it yet :p ) Both apparently have tradeoffs.
Son of Cain
Son of Cain
LoL, nice link! Deals with singletons' implementantion in detail. Seems like everything is covered, concerning implementation.
a.k.a javabeats at yahoo.ca
someboddy
someboddy
Correct me if I am wrong, but how will "return SingletonHolder.singleton;" work is SingletonHolder.singleton is declared private? I thought inner classes can access their outher classes private methods and properties, not vica versa.
-----------------------------------------Everyboddy need someboddy!
SamLowry
SamLowry
Private

Private seems to mean "accessible only in this .java file".


What's interesting about it is that the VM does not know about inner/nested classes, so that these are just compiled as separate .classes. But then the VM should not allow access to private members in either direction (inner class may not access outer privates, outer class may not access inner privates, since they are separate classes according to the VM).

Sun's solution to this is to insert extra "package-internal" methods which give other classes direct access to the private members.
lucky_monkey
lucky_monkey
Quote:
Original post by Tebriel
Quote:
Original post by BitMaster
Are you sure you need an instance of the singleton or are you doing that simply to say "I have implemented the Singleton Pattern"? Wouldn't a class with all static data and methods be enough?


Actually I had the same question myself earlier. I have a few guesses as to the answers, but rather than throwing stuff out I'll wait for someone more enlightened in Java to illustrate why this is better.

I suspect it has mostly to do with future changes: "if you decide that the class should no longer be a singleton, you may simply change the implementation of getInstance."
Wouldn't a factory be a better model for that situation?
Whackjack
Whackjack
The reason you would want to use a singleton is if it you only want one instance per VM and you need to maintain state. If your class is only going to be performing actions (i.e. does not have state), then a class full of static methods would be the approach to take. However, this isn't a good OO approach, but sometimes it's necessary.
I think some of you might be mistaking a factory with a singleton. Factories exist solely to create instances of classes. A good example might be a MonsterFactory that spits out instances of classes derived from a IMonster interface. This factory would not need to maintain any state (unless you're counting how many monster you are creating, but that should be done elsewhere.)
Son of Cain
Son of Cain
Factory != Singleton.

But there are times you may wish to create a "Singleton Factory". In my case, our project has a Factory class for resources, which is also a Singleton class, because it needs to maintain state, and its instantiation is expensive, so we want to do it only once and reuse it every time.

Such situations are the reason that causes people to misunderstand the purpose of these design patterns; because game programming often disturbs a programmer's mind, making he do evil things ;)

Son Of Cain
a.k.a javabeats at yahoo.ca
5MinuteGaming
5MinuteGaming
I don't see why you would want an implementation for this sort in the first place when you can just use the following for Singleton classes.

public final class SingletonClass {

public static int var1 = 0;
public static String name = "I am a Singleton";

}

With Static members.

It seems that you are confusing Singleton with one instance of an object. Just because you only use one instantiation of an object doesn't mean it has to be a singleton you can still keep it with its associated object.

If you want to have the object accessible to the entire program just make the variable that holds it a public Static member in any class within the program that way you aren't wasting time creating your own Singleton class. Or make a "final" class which holds all your related global data. Because thats basically what a Singleton is it's a global instantiation of a class.

Java API uses singletons such as java.lang.System java.lang.Math both of which are "final" classes. I suggest you implement all your singletons this way.
Zahlman
Zahlman
As noted, "static classes" are perfectly capable of maintaining state, and they certainly allow you to avoid all the usual problems with just making things "global" - because you can control access via the methods and doing all the usual encapsulation tricks.

The Singleton pattern is already widely regarded as overused - and that's in C++. Java further (for the most part - you can still cause problems with reflection apparently, but if you get bitten by that, I say you deserve it for working some unbelievable combination of deep magics) eliminates one of the main problems that the pattern actually might deal with in C++, i.e. the static order of initialization problem. Classes get all their static stuff initialized at first reference, so there is no chance of something not being uninitialized when it's needed - unless perhaps you have some circular reference problem, but then you'd be screwed *anyway*. You can do any necessary setup work in an init() method, and there is also the option of using a 'static initializer' block (which I personally find quite elegant, except when the init() is required anyway to control timing).

As for "you might decide to make it non-Singleton later", I hold this sort of argument in very low regard - it reeks of YAGNI. My experience has taught me that the best policy is to only design for changes that you have good reason to expect to make.

Note, however, that sometimes a Singleton "instance" is required in Java when exposing a completely static interface - for internal use (thus private) by the class:

public class MainGameLoop extends Canvas implements Runnable {  private static Thingy x; // and whatever other data  private static MainGameLoop mgl; // <-- here.  // Note that since there is only one instance, the actual MGL object can be  // "empty", relying on all the other static data members - but we still need  // that MGL object for callbacks. Its presence (non-null-ness) also verifies  // that class initialization has occurred.  public static void main(String[] args) {    mgl = new MainGameLoop();    new Thread(mgl).start();  }  // These two are public so that AWT/Swing/etc. can see them, but they are  // not part of the public interface as far as your app is concerned :/  public void run() { /* implement callback */ }  public void paint(Graphics g) { /* implement callback */ }  // Part of public interface: request repainting  public static void draw() { mgl.repaint(); } // and paint() will be called later}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.