5 ms·
As a video game programmer, I use the Singleton pattern quite often. For example, "TextureMgr", "MaterialMgr", "ModelMgr", "GrSubsys" (for Graphics Subsystem),
by palish 16y ago
As a video game programmer, I use the Singleton pattern quite often. For example, "TextureMgr", "MaterialMgr", "ModelMgr", "GrSubsys" (for Graphics Subsystem), etc..
The most beautiful Singleton code I've seen in C++ is:
class GrSubsys
{
public:
GrSubsys();
~GrSubsys();
};
extern GrSubsys* gGrSubsys;
... then the constructor and destructor are written such that you can startup/shutdown the singleton as follows:
//-------------------------------------------------------
void
App_Startup()
{
// initialize graphics subsystem.
new GrSubsys;
}
//-------------------------------------------------------
void
App_Shutdown()
{
// shutdown the graphics subsystem.
delete gGrSubsys;
}
//-------------------------------------------------------
int
main()
{
// startup the engine.
AppStartup();
// enter the per-frame application loop.
while ( AppFrame() )
{
}
// shutdown the engine.
AppShutdown();
return 0;
}
Shrug. A friend introduced it to me, and I liked it a lot. The same concept can be easily applied to C, too.
- latch 16y agohow much unit testing do you do?
- palish 16y agoA better question might be, "Would this pattern impact our ability to write unit tests?" I believe the answer is "No." Let's say the module Foo depends on the Graphics subsystem. That is, Foo.cpp has the code: #include "GrSubsys.h" //------------------------------------------------------- Foo::Foo( const string& name ) { // fetch a handle to our model (loading it if necessary). _model = gGrSubsys->GetModel( "models/" + name ); } //------------------------------------------------------- bool Foo::IsValid() { return ( _model != NULL ); } In order to write a unit test that takes into account the aforementioned Singleton pattern, you might write: //------------------------------------------------------- void Test_EngineComponents() { // prepare for science. AppStartup(); //========================== // Test #1 - Foo //========================== { // load a Foo entity. Foo* sunTzu = new Foo( "test/warlord" ); // verify the entity loaded successfully. assert( sunTzu->IsValid() ); // shutdown. delete sunTzu; } // conclude our science. AppShutdown(); } and AppStartup() is the function which initializes the subsystem singletons (and those will initialize their manager singletons). It's about discipline. Any fool can butcher with any tool.
- hartror 16y agoUnless I have missed something about unit testing somewhere I am pretty sure that fails the "unit" part of unit testing. Unless that "#include GrSubsys.h" is actually importing a mock graphics subsystem.
- palish 16y agoA mock graphics subsystem isn't possible since it depends directly on the video card.
- hartror 16y agoSorry fella but you don't understand the concept of unit testing. I suggest you do some reading on the subject. http://en.wikipedia.org/wiki/Unit_testing http://en.wikipedia.org/wiki/Unit_testing
- palish 16y ago"In a unit test, mock objects can simulate the behavior of complex, real (non-mock) objects and are therefore useful when a real object is impractical or impossible to incorporate into a unit test." Why would you want to simulate the graphics subsystem (and therefore the video card)? The goal here isn't performance testing. It's to check whether the engine works.
- hartror 16y agoYou aren't testing the engine. You are testing that the unit, in your example the class Foo, responds correctly to the state and inputs you provide it. Decoupling those responses from other units such as the graphics subsystem gives you the assurance that under the tested conditions the unit works as intended. What you are talking about is a regression or functional test. Same genus different species, still very useful but not the same tool. Edit: Going to bed, if someone would like to explain by morning why this needed to be down voted so brutally I would be much obliged!
- malkia 16y agoWe used a lot of singletons (also video game deveoper) in the past, to the point where the code is unreadable: some_system::get_instance()->MemberFunc(), instead of sys->MemberFunc() Problem came apparent when somebody had made the Camera singleton, and it was singleton... Nowadays we have one keyboard, one mouse, one printer... We used to have one DISPLAY, even one WINDOW (fullscreen), and one JOYSTICK. Just to get the point...