Thursday, November 03, 2005

Design Patterns

Well, it looks like I am learning some things at school.

In my Object Oriented Design class, we were discussing the usefulness of the singleton class. I've been doing just this before, but in a less than elegant manner.

First, a singleton is an object that can only be instantiated once. It handles this by making its construtor(s) private, and having a class method called "instance", which returns a pointer to an instantiated object. This pointer being a class attribute of the said class.

Now, the elegance of this method is that it doesn't pollute the global namespace (in C++). I've always done something along these lines:


static Whatever * instance = NULL;


Whatever * Instance(void)
{
if( instance == NULL )
instance = new Whatever();
return instance;
}


Now, in my implementation, there's a big ugly function "::Instance()" in the global namespace, which is fine for small applications, but lousy for larger ones, or libraries.

The singleton fixes this by having its initializer scoped by the class name.

Nice.

=====

Some handy links:

5 comments:

Anonymous said...

It looks like you are learning something at school....I see that you are enjoying linear algebra as well.

Pete said...

Mirek:

How is that cleaner? It throws an exception, which (IMHO) are garbage, because they can bring about memory leaks in non-managed pointers.

But how does one fetch the pointer/reference to the 'singleton' object? Does your version use a class method/attribute as well?

Pete said...

Mr Big:

Oh yes-- Linear algebra is just 'fantastic'. Out of all of my classes, it's the one that takes up the most of my time (there's a lot of pencil work that needs to be done in order for me to firmly grasp the material, while most of the other classes' material sticks from just listening to the lecture).

You're more than welcome to take my spot in class ;)

Anonymous said...

Whenever I have a choice between preventing a behaviour at compile time, or detecting it at run time and throwing an exception, I always choose compile time. The compiler is your friend. That's why we don't all have our functions take void pointers, attempt to cast them to whatever we're really expecting, and throw exceptions when they aren't.

Exceptions are slow. Exceptions can cause memory leaks. Exceptions don't provide guidance the way compiler-enforced structure does. They have their place, but not in an implementation of singleton.

BTW the implementation shown here is NOT thread safe, it's just to illustrate the concept. Herb Sutter had a fantastic PDC talk this year in which he showed it wasn't thread safe, showed a way around it, showed why that wasn't always thread safe, showed a way around that and so on. It ended up a LOT of code... concurrency is hard. Search for "Herb Sutter concur PDC" and you'll find the talk.

Kate

Pete said...

Wow-- and hour and sixteen minutes! I'll have to view that talk later.

(off topic, but...)

I seem to recall an old issue of the CUJ in which H. Sutter talks about the use of the boost::shared_ptr. Here's a link to a (somewhat) related discussion of his:

http://www.gotw.ca/gotw/056.htm

Now, it's also nice to see that the C++/IOS committee have decided to add the shared_ptr template to std::tr1

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf (2.2.1)

Exceptions are nice in Java, but I've never really liked them in C++. Unless you have a big ugly:

catch( ... )

in your main loop, then there's no compile-time provision that any of your functions that call exception-throwing functions will catch them appropriate.

if( ( object = f() ) != NULL ) { .. }

is your friend ;) (I'll never completely shake my C coding habbits).