1

I have a Gui Class, which is a Singleton, because many other classes have to use methods of the Gui and there should only be one instance of Gui at any time.

I also have the Player Class(is kind of an Audioplayer), which also is a Singleton.

When I start the Gui, I tell the player to get the current status (this creates a new instance of the player) and display it on the Gui. Therefore, the player creates an new instance of the Gui, because the Constructor of the Gui hasn't finished yet.

So, this creates an endless recursion. I'd like to keep the Singletons pattern. Is there a way to set instance in the getInstance() to something else than "null", even if the Constructur hasn't finished yet?

Thanks

Martin
  • 155
  • 1
  • 8
  • If you still want to use singleton a simple would be use a synchronization block, Example: public static Gui getInstance(){ // Synchronization is expensive therefore do a check outside. if(instance == null){ synchronized(Gui.class){ // After getting control check again if some other // thread as already updated the instance. if(instance == null){ instance = new Gui(); } } } return instance; } – Shailesh Kumar Dayananda Mar 26 '17 at 04:39

4 Answers4

2

I would perhaps avoid the singleton pattern altogether. As you've discovered it makes controlling the creation lifecycle difficult.

Instead I would create a GuiManager, which creates the Gui and then injects it into the appropriate components that need to know about it ? This is called inversion of control (or dependency injection) and avoids the need for global state. The benefits include making testing easy (since a surrounding framework controls the lifecycle of the objects) and the creation of these objects is predictable.

Community
  • 1
  • 1
Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • Isn't it bad code, if I have to give every class an instance of the gui in their constructor? – Martin Mar 14 '13 at 15:22
  • @user1894572 not necessarily. why would you think it is bad? – Aboutblank Mar 14 '13 at 15:24
  • I would hope it's not every class. But (say) a Player object could be created/managed via a PlayerManager, and that could refer to a Gui and manage the Player/Gui interactions. – Brian Agnew Mar 14 '13 at 15:26
  • Because its a little complicated. If there is a Class, which is created in another class, I have to give this first class the gui, even if this first class doesn't really need the gui. – Martin Mar 14 '13 at 15:27
  • Its not mandatory that you do dependency injection through constructor only. You can use setters also. – Atul Mar 15 '13 at 01:31
0

create a initialize function

public class Gui
{
    public static Gui instance;
    public static Gui getInstance()
    {
        if(instance == null)
        {    
            instance = new Gui();
            instance.initialize();
        }
        return instance;        
    }

    private Gui()
    {

    }

    private initialize()
    {
        // do constructor work here
    }
}
x4rf41
  • 5,184
  • 2
  • 22
  • 33
0

I would use a static initialization block. This gets called when the class is being constructed. not when an object is being created. and its called only once. see more

greenkode
  • 4,001
  • 1
  • 26
  • 29
0

This recursion is a symptom of a more general design problem. You could certainly try to solve it by "leaking" the instance reference from within the constructor or defer "construction" to some initialization method you call later (possibly lazily), but I would not recommend this1.

Why does the GUI and the Player class have to be singletons and have to know about each other and more specifically, have to know each other during construction? Is there a reason other than 'It's more convenient' to have global access to some object? Not that convenience is unimportant, but it should usually not be the only reason for a design decision.

A better approach would be to get rid of the singletons althogether, because there is no real reason that there cannot be two instances of a Player and a GUI at the same time. Of course, you will probably only have one of each in your program, but that is not the purpose of Singletons.

Also, you should have the dependency only in one direction. Try to think about what can exist without the other and what cannot. I would think the GUI should depend on the Player, as you probably could imagine having a Player without a GUI, but a GUI without a Player makes no sense at all. So you first construct a Player and then construct a GUI and pass it the Player instance it operates on. If you think you need access to your GUI instance from everywhere inside the Player, you should rethink you design and try to make those objects more independent. This usually can be done by using the Observer pattern and let the GUI listen for changes/actions/stuff that happen. This way, your application code does not know about the GUI at all. However, within you GUI, you can pass around the instance of the GUI as much as you like.

Regarding the idea of introducing a 'Manager' object or the Factory pattern: it might be useful, but you can certainly do all of what I said above without that and still have a sane design. I generally would adivse against 'Manager' classes, as they tend to do too many things and are typically kind of a Singleton in disguise. Factories, however, can be useful, but only if you want to decouple actual construction of things from their usage, for example to allow different types of GUIs to be implemented later.

So a simple implementation would look like this:

public static void main(...) {
    Player player = new Player();
    // maybe some other stuff to configure/set up the player

    GUI gui = new GUI(player);
    gui.show(); // or something similar
}

If you wanted to use factories, you could of course replace the new ... expressions with calls to the factories you would have to obtain before.

1  Why? Well, for example what would happen if you construct the GUI successfully, but later on fail to initialize it, e.g. an exception is thrown? You would need some way to communicate this 'invalid' state to all objects which already obtained the GUI instance. Also, you would have to make sure nobody uses the GUI instance before it is initialized.

Simon Lehmann
  • 10,737
  • 4
  • 41
  • 53
  • This is a very good Idea. I really should avoid the double dependency. I also should use some kind of "Manager", which is called at the very beginning and which calls all the constructors and passes the instances. I think this is the best answer. – Martin Mar 14 '13 at 15:37