Jump to content
  • Advertisement
Sign in to follow this  
RealMarkP

Help me get rid of a singleton

This topic is 3909 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. I'm currently using the singleton pattern for two classes. First being an error logging class (which I'm not too concerned about), and the second being my event passing system. This event system handles messages from all over the system and properly passes them along to other parts of the system, much like a regular message pump would (via PeekMessage, DispatchMessage). I was wondering, since this class is accessed from many places to fire events, if there was a better pattern I could use to build this on. Or better yet, if anyone can suggest a better approach of routing events around my (fairly large) system.

Share this post


Link to post
Share on other sites
Advertisement
To remove singletons, I generally start with refactoring. I search for each instance of TheSingletonClass::getInstance(). At each location, I replace this with this a reference to the singleton class, instead of the getInstance. Then, I add a member variable to the class that is using it as a reference or pointer. e.g.:


class Whatever
{
private:
TheSingletonClass& singleton_;
};



or


class Whatever
{
private:
TheSingletonClass* pSingleton_;
};



Next step, is for the class who was previously using the singleton globally, I add a pass-by-reference to the constructor of the class. Like so:


class Whatever
{
public:
Whatever(TheSingletonClass& p_singleton);
};



Now that we have that, the class is decoupled from the singleton instance. The final step is to go to the class who created this one and have it pass through the singleton. If the calling class doesn't have non-global access to the singleton, you'll have to rinse and repeat with that class. Ultimately, this leads to breaking up the singleton dependency.

When I finally have no more references to TheSingletonClass::getInstance() except at the highest level, I finally change this one last spot to create the class on the stack and remove the getInstance call.

It can be a lengthy process, but if you use refactoring techniques like what I mentioned, generally the compiler can help you out as you go along if you forget something, and you can hit points where you can take a break and try things out, so there's minimal risk of breaking existing code.

Share this post


Link to post
Share on other sites
Quote:
Original post by RealMarkP
This event system handles messages from all over the system and properly passes them along to other parts of the system, much like a regular message pump would.

Eesh. That's going to be a difficult one. How are senders and receivers matched up by the event system? Do they subscribe to named messages, or are the connections hardcoded, or what?

Share this post


Link to post
Share on other sites
To elaborate a short bit on Rydinare's solution, you can also use a Design Pattern I have dubbed 'inherited properties'. This consists in allowing an object to be created from another, similar object, thereby inheriting that object's properties (unless someone sees fit to override those properties in another way). For instance, a base class to inherit this singleton could be:

class HasMessageSystem
{
protected:

// The context
MessageSystem &msg;

public:

// Create a brand new object
HasMessageSystem(MessageSystem &msg) : msg(msg) {}

// Inherit context from another object
HasMessageSystem(const HasMessageSystem &other) : msg(other.msg) {}
};


By using multiple inheritance to propagate the individual base clases where they are needed, you achieve the pattern. From then on, you only need to pass an object to the object it is creating for that object to receive the same 'global' references as that object, while retaining the possibility to bind another reference instead.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
To elaborate a short bit on Rydinare's solution, you can also use a Design Pattern I have dubbed 'inherited properties'. This consists in allowing an object to be created from another, similar object, thereby inheriting that object's properties (unless someone sees fit to override those properties in another way). For instance, a base class to inherit this singleton could be:

class HasMessageSystem
{
protected:

// The context
MessageSystem &msg;

public:

// Create a brand new object
HasMessageSystem(MessageSystem &msg) : msg(msg) {}

// Inherit context from another object
HasMessageSystem(const HasMessageSystem &other) : msg(other.msg) {}
};


By using multiple inheritance to propagate the individual base clases where they are needed, you achieve the pattern. From then on, you only need to pass an object to the object it is creating for that object to receive the same 'global' references as that object, while retaining the possibility to bind another reference instead.


That can work. My only slight distaste is it violates is-a/has-a rules. A class which uses a HasMessagingSystem is not a HasMessagingSystem. So, inheritance is a little awkward.

Share this post


Link to post
Share on other sites
Quote:
To remove singletons, I generally start with refactoring.


Thanks, but my problem is not decoupling the singleton structure form my class. Rather its a design problem. How can you send messages to something that you don't know exists.

Quote:
Eesh. That's going to be a difficult one. How are senders and receivers matched up by the event system? Do they subscribe to named messages, or are the connections hardcoded, or what?


They respond only to the messages they register to. So a window will receive a Size event, as will the Rendering context (because I have to resize the backbuffer). I know its a fairly complex thing to place inside my engine, and the only way I could see singletons used in this example. Alternatively, I can create an Event class that already knows about the event manager, so that each class doesn't have to call the event Manager's functions in order to post a message. But that is almost like a deferred solution to another class. If the event manager is not the singleton, then the event class is. Another example would be that my context (DirectX) detects it lost focus, it has to send a message to my resource pool so that textures, meshes, buffers are pushed back into the system (Ivalidated & restored).

Alternatively, I can use the windows message pump to send messages to the event manager. Thoughts?

Quote:

By using multiple inheritance to propagate the individual base clases where they are needed, you achieve the pattern. From then on, you only need to pass an object to the object it is creating for that object to receive the same 'global' references as that object, while retaining the possibility to bind another reference instead.


In your example, the programmer would have to know the event system ahead of time, in order to pass in the reference into the constructor. This is what I'm trying to avoid. Am I misunderstanding your explanation?

Share this post


Link to post
Share on other sites
Quote:
Original post by Rydinare
(stuff)

The problem with such a heavy-handed and mechanical approach is that it encourages spurious dependencies. A class ends up holding a reference to a TextureLoader, not because it has anything to do with textures or loading, but because five classes down the line of construction, something else did. I guess it's fine as a way to start, but by itself it's just doing the same thing as the singleton with more code.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by Rydinare
(stuff)

The problem with such a heavy-handed and mechanical approach is that it encourages spurious dependencies. A class ends up holding a reference to a TextureLoader, not because it has anything to do with textures or loading, but because five classes down the line of construction, something else did. I guess it's fine as a way to start, but by itself it's just doing the same thing as the singleton with more code.


Well, there's two options I'm aware of: globals or passing things around. Singletons don't particularly bother me in of themselves, it's just an over-engineered global. The global aspect is what gets me. Neither option that I mentioned is necessarily great, but passing references around does not actually create concrete dependencies, as what's being passed around is merely pointers or references, which can be forward declared. It can also be a more generic interface (e.g.: ILogger for logging capabilities).

But, I understand your point. I have major issues with globals since they break the normal flow and don't allow flexibility. As to where, say this class is a logger, a class a level down could choose to pass through a different logging mechanism without needing tricky logic all over the app to handle it.

I guess the question I'd have for you is how to eliminate the globals without passing the reference around all over the place. I've never seen a great answer to this other than a strict redesign to decouple things more.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
The problem with such a heavy-handed and mechanical approach is that it encourages spurious dependencies. A class ends up holding a reference to a TextureLoader, not because it has anything to do with textures or loading, but because five classes down the line of construction, something else did. I guess it's fine as a way to start, but by itself it's just doing the same thing as the singleton with more code.


I guess my options are either to use a global variable, a singleton or static variable, or by passing around a reference to the event manager?

Share this post


Link to post
Share on other sites
Quote:
Original post by RealMarkP
They respond only to the messages they register to. So a window will receive a Size event, as will the Rendering context (because I have to resize the backbuffer). I know its a fairly complex thing to place inside my engine, and the only way I could see singletons used in this example. Alternatively, I can create an Event class that already knows about the event manager, so that each class doesn't have to call the event Manager's functions in order to post a message. But that is almost like a deferred solution to another class. If the event manager is not the singleton, then the event class is.

The thing that makes this so difficult is that your event manager gives every other class in your system carte blanche to couple with any other classes it feels like. You might as well make it a struct containing every object you've created. The alternative would be the different objects registering themselves for notification directly with the object that'll be raising the event; that is, you can't get events from an object unless you know about that object. This is possible in carefully designed applications, but it is likely to be extremely difficult to retrofit elegantly. You might consider sticking with the singleton.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!