Single Object Instance Techniques

J

JohnQ

Why would anyone write:

class SomeThing // class littered with non-domain single-instancing code :(
{
private:
SomeThing();
static SomeThing* pInstance_;
public:

static SomeThing* getInstance()
{
if(!pInstance_)
{
pInstance_ = new SomeThing();
}
return pInstance_;
}
};
SomeThing* SomeThing::pInstance_ = 0;

instead of this:

class SomeThing // class unencumbered by single-instancing concerns :)
{
public:
SomeThing();
};

SomeThing* GetSomeThing() // single-instancing accessor function
{
static SomeThing* thing = new SomeThing();
return thing;
}

???

Is it because the second example only solves the problem but doesn't ensure
that someone won't call the constructor elsewhere? That's it isn't it.
Single-instance techniques help with the initialization order problem, and
the second form works great for that. I don't think single instance control
belongs in a domain class. 'SingleInstancer' should be a template class.
What's your opinion?

John
 
E

emery.denuccio

There is no advantage. If I saw that code I would guess someone came
from an object oriented only language, and didn't know of direct
namespaces. It's clearly an attempt to allow only one instance of the
class, but it doesn't actually enforce it. Alternative, a struct with
only static member functions could have been used.

Another disadvantage is that it makes it impossible for the class to
be allocated on the stack faster.
 
P

Phlip

JohnQ said:
Why would anyone write:

class SomeThing // class littered with non-domain single-instancing code
:(
{
private:
SomeThing();
static SomeThing* pInstance_;

I don't have the book Design Patterns to hand. Under Singleton, does it show
the above code, or this correct code below?
SomeThing* GetSomeThing() // single-instancing accessor function
{
static SomeThing* thing = new SomeThing();
return thing;
}

If you must Singleton, do it like that.

However, Singleton is a very abusable pattern when it enables rampant
coupling. The "instantiate once" motivation is not the same as the
"available to everyone like a big fat global" motivation. The latter is an
antipattern!
... 'SingleInstancer' should be a template class.

Such a template is often the result of a junior effort with Singleton. I
don't think it solves the problem how to prevent secondary instantiation of
the templated type.

Furtherless, if you have unit tests, you _need_ secondary instatiation, so
you can fake objects for your tests!

Singletons should be treated with high suspicion.
 
E

emery.denuccio

Single-instance classes are contradictory to entire idea of OOP.
You're essentially making an object, and using object syntax, just for
its namespace. I recommend instead using an actualy namespace and a
procedural paradigm.
 
E

emery.denuccio

Single-instance classes are contradictory to entire idea of OOP.
You're essentially making an object, and using object syntax, just for
its namespace. I recommend instead using an actual namespace and a
procedural paradigm.
 
E

emery.denuccio

Single-instance classes are contradictory to entire idea of OOP.
You're essentially making an object, and using object syntax, just for
its namespace. I recommend instead using an actual namespace and a
procedural paradigm.
 
E

emery.denuccio

Single-instance classes are contradictory to the entire idea of OOP.
You're essentially making an object, and using object syntax, just for
its namespace. I recommend instead using an actual namespace and a
procedural paradigm.
 
I

Ian Collins

Single-instance classes are contradictory to the entire idea of OOP.
You're essentially making an object, and using object syntax, just for
its namespace. I recommend instead using an actual namespace and a
procedural paradigm.
Why have you posted the same message (without any context) four times?
 
E

Emery

Why have you posted the same message (without any context) four times?

Sorry. Google groups was bugging out on me. It was giving me failure
messages, then it decided to work on my fourth or fifth attempt. It
appears to be working fine now, even though only the final message
shows up in Google groups, but the total-messages count is in excess
of 4. *shrugs*
 
A

Adrian Hawryluk

Phlip said:
I don't have the book Design Patterns to hand. Under Singleton, does it show
the above code, or this correct code below?


If you must Singleton, do it like that.

Aren't those two equivalent Philip? The only difference that I see is
that the pointer is directly class accessible and accessible to the
outside only via the function (which does the test on first use
explicitly, instead of implicitly by way of the static inside of the
function). Although, I guess that the compiler may be able to do some
optimisations using the implicit test? What do you think?
However, Singleton is a very abusable pattern when it enables rampant
coupling. The "instantiate once" motivation is not the same as the
"available to everyone like a big fat global" motivation. The latter is an
antipattern!


Such a template is often the result of a junior effort with Singleton. I
don't think it solves the problem how to prevent secondary instantiation of
the templated type.

Do you say this because of how some linkers may work? I think that most
(if not all) of the newer linkers are supposed to amalgamate all
statically linked multiple instances of the same templates. DLLs and
shared memory spaces are a different matter. It would require extra
care and would have to incorporate that into your design of your
application system.
Furtherless, if you have unit tests, you _need_ secondary instatiation, so
you can fake objects for your tests!

I don't agree. You can do unit tests on a singleton. In fact, your
domain is somewhat narrowed with a singleton as since there is only one
instance floating around, you don't have to worry about interactions
with others of the same type, and can optimise based on that pattern.
Singletons should be treated with high suspicion.

Singletons are just like most patterns. Design patterns are a way of
sharing insight on common problems and are useful. This limits but does
not eliminate the abuse of such patterns.


Adrian
--
_____________________________________________________________________
\/Adrian_Hawryluk BSc. - Specialties: UML, OOPD, Real-Time Systems\/
\ My newsgroup writings are licensed under the Creative Commons /
\ Attribution-Noncommercial-Share Alike 3.0 License /
\_____[http://creativecommons.org/licenses/by-nc-sa/3.0/]_____/
\/______[blog:__http://adrians-musings.blogspot.com/]______\/
 
S

SasQ

Dnia Sat, 17 Mar 2007 02:48:54 +0000, JohnQ napisa³(a):
Why would anyone write:

class SomeThing
{
private:
SomeThing();
static SomeThing* pInstance_;
public:
static SomeThing* getInstance()
{
if (!pInstance_)
{
pInstance_ = new SomeThing();
}
return pInstance_;
}
};
SomeThing* SomeThing::pInstance_ = 0;

Maybe because he's a stuntman ;)
Think about where is a delete operator called for the
object pointed by pInstance_ ? When is a destructor called?
Answer is: never :p and it's not good :/
The other flaw is returning a pointer to internal data,
because it gives an opportunity for someone to call 'delete'
on this pointer and deallocate that internal, private object.
There is also nothing to stop you from copy-construct the
additional objects of that class, because copy constructor
wasn't declared private.

Instead, I advice you the Meyers's approach:

class SomeThing
{
public:
// Returning by reference ensures that calling delete
// on the returned object will cause a compiler error.
static SomeThing& getInstance()
{
// The following object will be allocated in a static
// memory, but initialized only once, upon first call
// of this function, with the use of private constructor.
// Further calls will only return that single instance.
// Object will be properly destructed [using destructor]
// when the program ends.
static SomeThing instance;
return instance;
}
// ...other public interface...

private:
// Declaring the following as private prevents illegal
// creations of more instances.
SomeThing();
SomeThing(const SomeThing&);
SomeThing& operator=(const SomeThing&);
};

Example of use:

SomeThing obj = SomeThing::getInstance();
obj.someMethod();
delete obj; //error: not a pointer :)
SomeThing::getInstance().someMethod();
class SomeThing // class unencumbered by single-instancing concerns :)

If you don't want only one single instance, but you only want to
have global access to that object and prevent static initialization
order fiasco, you don't need that pattern.
SomeThing* GetSomeThing() // single-instancing accessor function

Accessor? But it's not a member of any class.
I would rather call it factory/creation function ;)
{
static SomeThing* thing = new SomeThing();
return thing;
}

Yes, that function returns always the same one instance of
SomeThing, but doesn't prevent from creating more instances
in the other place in a program.
Single-instance techniques help with the initialization
order problem

But not ONLY with that ;)
and the second form works great for that.

It's not. Still someone may try to create some global
instances depending on other global objects in a program
[and their initialization before theirs].
I don't think single instance control belongs in a
domain class.

And what do you think about a cloning/copying domain? :)
'SingleInstancer' should be a template class.

Or an interface. But it's not that simple.
 
S

SasQ

Dnia Sat, 17 Mar 2007 16:23:02 +0100, SasQ napisa³(a):
Example of use:

SomeThing obj = SomeThing::getInstance();

Sorry for a little mistake, I meant:

SomeThing& obj = SomeThing::getInstance();

of course ;)
 
J

JohnQ

SasQ said:
Dnia Sat, 17 Mar 2007 02:48:54 +0000, JohnQ napisa³(a):
Why would anyone write:

class SomeThing
{
private:
SomeThing();
static SomeThing* pInstance_;
public:
static SomeThing* getInstance()
{
if (!pInstance_)
{
pInstance_ = new SomeThing();
}
return pInstance_;
}
};
SomeThing* SomeThing::pInstance_ = 0;

Maybe because he's a stuntman ;)
Think about where is a delete operator called for the
object pointed by pInstance_ ? When is a destructor called?
Answer is: never :p and it's not good :/
The other flaw is returning a pointer to internal data,
because it gives an opportunity for someone to call 'delete'
on this pointer and deallocate that internal, private object.
There is also nothing to stop you from copy-construct the
additional objects of that class, because copy constructor
wasn't declared private.

Instead, I advice you the Meyers's approach:

class SomeThing
{
public:
// Returning by reference ensures that calling delete
// on the returned object will cause a compiler error.
static SomeThing& getInstance()
{
// The following object will be allocated in a static
// memory, but initialized only once, upon first call
// of this function, with the use of private constructor.
// Further calls will only return that single instance.
// Object will be properly destructed [using destructor]
// when the program ends.
static SomeThing instance;
return instance;
}
// ...other public interface...

private:
// Declaring the following as private prevents illegal
// creations of more instances.
SomeThing();
SomeThing(const SomeThing&);
SomeThing& operator=(const SomeThing&);
};

Example of use:

SomeThing obj = SomeThing::getInstance();
obj.someMethod();
delete obj; //error: not a pointer :)
SomeThing::getInstance().someMethod();
class SomeThing // class unencumbered by single-instancing concerns :)

If you don't want only one single instance, but you only want to
have global access to that object and prevent static initialization
order fiasco, you don't need that pattern.
SomeThing* GetSomeThing() // single-instancing accessor function

Accessor? But it's not a member of any class.
I would rather call it factory/creation function ;)

It's a factory the first time it is called. After that, it is an accessor.
{
static SomeThing* thing = new SomeThing();
return thing;
}

Yes, that function returns always the same one instance of
SomeThing, but doesn't prevent from creating more instances
in the other place in a program.
Single-instance techniques help with the initialization
order problem

But not ONLY with that ;)
and the second form works great for that.

It's not. Still someone may try to create some global
instances depending on other global objects in a program
[and their initialization before theirs].
I don't think single instance control belongs in a
domain class.

And what do you think about a cloning/copying domain? :)

I don't know what you're talking about with that.
Or an interface. But it's not that simple.

I guess the work on this topic seems to be on how to create one of those
things for other people to use. If you're building something just for your
own use, you don't need all the controls. Things like that are hard to build
outside of the language implementation probably. Just like it's hard if not
impossible to get a class to act like a pointer.

I had a follow-up question to post after this one about the threading
concerns (aka, DCL issues), but it escapes me at this time. I'll post it if
I remember where I was going with this.

John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,197
Latest member
Sean29G025

Latest Threads

Top