If I need a second instance of an object as you said device for D3D I would use a multiton its the same as a singleton but it can handle "n" instead of 1 instances
besides that I would structure the code a little bit differently
e.g.:
activate contextrender something ....
activate another context
render something
deactivate context ...
I doubt that I will need another instance of any of my resource managers, since this is the point of a resource manager, to organize resources at one point and only pass handles to the other subsystems.
My way of designing software is some kind of bottom up with layering of subsystems to abstract the basics in the top layers thus reducing the code complexity a lot.
The result is extremely reuseable code and a growing code base, whose code quality improves with every project.
Game Enigne: Putting it all together (design)
Did you read the links I provided? They're not long but very educational. I was a singleton fan like yourself, then I started reading other peoples code and never seen them used in production code. Then I researched them a bit more and stopped using them for obvious reasons.
Well a singleton will let you do this. So your code, by your own admission is bad design. A singleton can be accessed by anything and everything. That's what a singleton is and allows. Now if your code is just for you and no one will EVER use it, then fine, code however you like.
Why do you only need one resource manager, one renderer? What if I want to start loading a second level in a second resource manager? What if I want to render another view to a different screen? None of this should involve the engine needing to be touched at all in a decent design. Heck in my engine you can have unlimited numbers of theses (the documentation can say "only implmenent this once!" but if the coder chooses not too, its not your place to stop him).
I don't have pointers being passed all over the place and events are not a bad thing or a bad design. I, like Riviera Kid, has a GeneralMgr class that holds starts up all the subsystems in order. It then passes pointers to the subsystems that need them, say Renderer to the SceneGraph (nothing else needs the Renderer), SceneGraph gets a pointer to the AudioMgr, AIMgr Gets a pointer to the SceneGraph and AudioMgr, etc. This is all done with one function then the classes know everything they need too and I never worry about it again. There is no more passing of pointers, etc.
The way my GeneralMgr is setup, it only allows single instances of what it wants, but if someone is using my engine on their own project (without the source say) they don't need to use GeneralMgr, they can make their own and startup 10 ResourceMgrs if they please. It took no more time to design/implement this then if I had done singletons and is non-restrictive.
Quote:
Clearly nobody would say the use of a singleton to access the sound manager in the collision code is good design.
Well a singleton will let you do this. So your code, by your own admission is bad design. A singleton can be accessed by anything and everything. That's what a singleton is and allows. Now if your code is just for you and no one will EVER use it, then fine, code however you like.
Why do you only need one resource manager, one renderer? What if I want to start loading a second level in a second resource manager? What if I want to render another view to a different screen? None of this should involve the engine needing to be touched at all in a decent design. Heck in my engine you can have unlimited numbers of theses (the documentation can say "only implmenent this once!" but if the coder chooses not too, its not your place to stop him).
I don't have pointers being passed all over the place and events are not a bad thing or a bad design. I, like Riviera Kid, has a GeneralMgr class that holds starts up all the subsystems in order. It then passes pointers to the subsystems that need them, say Renderer to the SceneGraph (nothing else needs the Renderer), SceneGraph gets a pointer to the AudioMgr, AIMgr Gets a pointer to the SceneGraph and AudioMgr, etc. This is all done with one function then the classes know everything they need too and I never worry about it again. There is no more passing of pointers, etc.
The way my GeneralMgr is setup, it only allows single instances of what it wants, but if someone is using my engine on their own project (without the source say) they don't need to use GeneralMgr, they can make their own and startup 10 ResourceMgrs if they please. It took no more time to design/implement this then if I had done singletons and is non-restrictive.
Quote:Original post by Basiror
If I need a second instance of an object as you said device for D3D I would use a multiton its the same as a singleton but it can handle "n" instead of 1 instances
Then why even bother with a singleton OR a multiton when much better design patterns exist?
Quote:
besides that I would structure the code a little bit differently
e.g.:
activate contextrender something ....
activate another context
render something
deactivate context ...
Maybe an example with something more code like.
Quote:
I doubt that I will need another instance of any of my resource managers, since this is the point of a resource manager, to organize resources at one point and only pass handles to the other subsystems.
But why couldn't someone that uses this in the future want two levels loaded at once but not managed by the same resource manager. Unless you can predict the future with 100% certainty why design future coders who use your engine into a corner?
Quote:
My way of designing software is some kind of bottom up with layering of subsystems to abstract the basics in the top layers thus reducing the code complexity a lot.
Keeping code complexity to a minimum should be all programmers goal (unless you're doing it for job security haha). Sadly, in the real world timelines usually mean its not possible.
Quote:
The result is extremely reuseable code and a growing code base, whose code quality improves with every project.
My non-singleton using code is the same and I'd say even more so since it has no restrictions. While you can change yours so you don't have them, I don't have to touch anything to do so.
I can take my AudioMgr, Renderer, ResourceMgr, etc out of my engine and in a matter of minutes having it working alone in a new project. As many of the sub systems as possible were developed as much as they could be stand alone, then inegrated into the engine so they're easy to extract and yet not a mess for the engine to use.
As a side note, I too am self-taught but I will never stop learning. I've helped a lot of friends with coding classes in college/university but have yet to see a teacher (I know they exist, heard about them on these forums) that accept singletons or global variables. The first time I heard this I called the teacher an idiot, then researched it a bit on forums and found out maybe he wasn't lol.
Anyways, long weekend!
Those ideas have all their good and bad aspects. Singletons are good because you do not need to write any further fixed pointers that will allow you to talk with other classes but on the other side, why does all need to be so explolited? As the colleague above said, why does a sound manager need to see the renderer singleton? I believe it can be achived much cleaner - Micro$oft also does not include any singletons in their DirectX SDK and it allso can work.
My question is about Class communication. For example:
I would like to have a cDirectX9 class that holds just the IDIRECT3D9DEVICE pointer and clearly initializes it. Also that class could open "n" render target windows like cRenderTarget. The problem is what about when the cRenderTarget window resizes and would like to notify cDirectX9 device? I would not like to say it like so:
class cDirectX9;//forward declaration
class cRenterTarget
{
cDirecrX9* m_pDirectX;
...
onResize() { m_pDirectX->Resize();
}
class cDirectX
{
std::vector<cRenderTarget*> devices;
}
or on the other way I allso do not like the idea:
cRenderTarget::onResize() { this->Invalidate ( cRenderTarget = dirty; }
and when the cDirectX comes in it's update look it checks the windows whenever they are dirty and resets the device.
The problem is, either I use forward declaration or have to implement some passive workaround. Can it be performed in a better way? I would like cDirectX to be a factory for cRenderTarget(s) but they should be able to communicate.
Thank you in advance!
It is very nice to see what kind of design patterns many different coders use.
My question is about Class communication. For example:
I would like to have a cDirectX9 class that holds just the IDIRECT3D9DEVICE pointer and clearly initializes it. Also that class could open "n" render target windows like cRenderTarget. The problem is what about when the cRenderTarget window resizes and would like to notify cDirectX9 device? I would not like to say it like so:
class cDirectX9;//forward declaration
class cRenterTarget
{
cDirecrX9* m_pDirectX;
...
onResize() { m_pDirectX->Resize();
}
class cDirectX
{
std::vector<cRenderTarget*> devices;
}
or on the other way I allso do not like the idea:
cRenderTarget::onResize() { this->Invalidate ( cRenderTarget = dirty; }
and when the cDirectX comes in it's update look it checks the windows whenever they are dirty and resets the device.
The problem is, either I use forward declaration or have to implement some passive workaround. Can it be performed in a better way? I would like cDirectX to be a factory for cRenderTarget(s) but they should be able to communicate.
Thank you in advance!
It is very nice to see what kind of design patterns many different coders use.
This thread has been a long debate about singletons, so let's get it back to the OP's question. Somebody earlier mentioned using message passing, which I second. You'll have to learn about data distribution management (DDM) to make message passing sane (message passing can slaughter your performance if your audio system, physics system, AI system, and all your game entities have to process and throw away your WINDOW_RESIZE message), but in my experience, message passing has really done a lot to reduce coupling between components.
Quote:Original post by Basiror
Why shouldn t I use singletons when I consider a subsystem as a whole? I won t bloat my code with them, its just a way to access data directly without passing a ton of function parameters
And they have the advantage that you can make them multithreading compatible on the fly opposed to simple global variables.
I see no reason why you shouldn t use singletons. In my opinion every sub system that exists only once should be represented by a singleton.
Careful how you make them thread safe, you need to use barriers.
Have a look at this paper.
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
Jack, use a centralized messaging system. Everyone sends messages to the same object with a recipient number on them. Have a stack for each system, place the item in the appropriate stack, and pop them off as need be. The windows system wouldn't need to know about the graphics system and the graphics system wouldn't have to know about the windows system. Nor would the messages to one system get in the way of another system. Thats how I would implement it at least.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement