C++ abstract (singleton) factory implementation...


 
Thread Tools Search this Thread
Top Forums Programming C++ abstract (singleton) factory implementation...
# 1  
Old 11-05-2012
C++ abstract (singleton) factory implementation...

I want to create an abstract factory template which will allow me to pass in an "ID" for a subclass and return the singleton instance of that class stored in the factory. It'd be easy to adapt for "multi-ton", but for its present use this isn't necessary.

The requirements are:

- I don't want to have to "register" the classes in some main class somewhere, I want them to register themselves as best as possible.
- I want the above to be done with as little boilerplate as possible.

This seems to be close to a Prototype pattern I found before, but I'm not sure I love it...the biggest downfall I see is that it requires a single instance of each type to be created just so it can do nothing with it but clone them.... I'm not fond of that.

So, I tried to create something myself, and it seems to be working, but if possible, I'd love it if some of y'all could comment (or send me somewhere else I can post it for comment). I've done a decent amount of C++, but not so much that I 100% trust myself without some peer review. Unfortunately, there aren't many other devs where I am with exhaustive C++ knowledge to review it either...so...I was hoping I could get a few extra eyes around here.

On the up-shot...if anyone finds it useful, steal it at will :-).

Here's the code so far:

First the template for the AbstractSingletonFactory:
Code:
#ifndef ABSTRACTSINGLETONFACTORY_H
#define ABSTRACTSINGLETONFACTORY_H

#include <map>

// forward declaration
template<typename T, typename, typename, T> class AbstractSingletonSubclass;

/**
 * Template class AbstractSingletonFactory
 *
 * Template params:
 *
 *   IDT - sub-class ID type, must be comparable, used to look-up a factory
 *           for each registered sub-class.
 *
 *   BCT - base class type -- the base class from which each sub-class shall
 *           inherit.
 *
 */
template<typename IDT, typename BCT> class AbstractSingletonFactory
{
	// friend to allow registration of sub-classes
	template<typename T, typename, typename, T> friend class AbstractSingletonSubclass;
	
public:
	AbstractSingletonFactory()
	{
	}
	
	~AbstractSingletonFactory()
	{
		typename std::map<IDT, BCT *>::iterator it;
		
		for (it = _singletonMap.begin(); it != _singletonMap.end(); ++it)
		{
			delete it->second;
		}
	}
	
	BCT *getSingletonInstance(IDT forId)
	{
		BCT *instance;
		
		typename std::map<IDT, BCT *>::iterator it;
		if ((it = _singletonMap.find(forId)) != _singletonMap.end())
		{
			instance = it->second;
		}
		else
		{
			IAbstractSingletonFactory *factory =
						AbstractSingletonFactory<IDT, BCT>::GetDirectory().getSubclassFactory(forId);
			
			instance = factory != NULL ? factory->createSubclassInstance() : NULL;
			
			if (instance)
			{
				_singletonMap.insert(std::pair<IDT, BCT *>(forId, instance));
			}
		}		
				
		return instance;
	}
	
private:
	class IAbstractSingletonFactory
	{
	public:
		virtual BCT *createSubclassInstance() = 0;
	};
	
	class SubclassDirectory
	{	
	public:
		SubclassDirectory()
		{
		}
		
		void setSubclassFactory(IDT forId, IAbstractSingletonFactory *factory)
		{
			_scFactoryMap.insert(
				std::pair<IDT, IAbstractSingletonFactory *>(forId, factory));
		}
		
		IAbstractSingletonFactory *getSubclassFactory(IDT forId)
		{
			IAbstractSingletonFactory *factory;
			
			typename std::map<IDT, IAbstractSingletonFactory *>::iterator it;
		
			if ((it = _scFactoryMap.find(forId)) != _scFactoryMap.end())
			{
				factory = it->second;
			}
			else
			{
				factory = NULL;
			}
			
			return factory;
		}
		
	private:		
		std::map<IDT, IAbstractSingletonFactory *> _scFactoryMap;
	};
	
	static void RegisterSubclassId(IDT id, IAbstractSingletonFactory *factory)
	{
		AbstractSingletonFactory<IDT, BCT>::GetDirectory().setSubclassFactory(id, factory);		
	}
	
	static SubclassDirectory &GetDirectory()
	{
		static SubclassDirectory theDirectory;
		
		return theDirectory;
	}
	
	std::map<IDT, BCT *> _singletonMap;
};

#endif // ABSTRACTSINGLETONFACTORY_H

Then the template for the AbstractSingletonSubclass:
Code:
#ifndef ABSTRACTSINGLETONSUBCLASS_H
#define ABSTRACTSINGLETONSUBCLASS_H

#include "AbstractSingletonFactory.H"

template<typename IDT, typename BCT, typename SCT, IDT SCID> class AbstractSingletonSubclass
{
protected:	
	static void AbstractSingletonSubclassInit()
	{		
		AbstractSingletonFactory<IDT, BCT>::RegisterSubclassId(SCID, &_factory);
	}
	
	class InitAbstractSingletonSubclass
	{
	public:
		InitAbstractSingletonSubclass()
		{
			AbstractSingletonSubclassInit();
		}
	};
	
private:
	class Factory : public AbstractSingletonFactory<IDT, BCT>::IAbstractSingletonFactory
	{
	private:
		BCT *createSubclassInstance()
		{
			return new SCT;
		}
	};
	
	static Factory _factory;
};

template<typename IDT, typename BCT, typename SCT, IDT SCID>
typename AbstractSingletonSubclass<IDT, BCT, SCT, SCID>::Factory
AbstractSingletonSubclass<IDT, BCT, SCT, SCID>::_factory;

#endif  // ABSTRACTSINGLETONSUBCLASS_H

Sample usage:

Code:
class NewClassBase
{
public:
	virtual int getId() = 0;

// boilerplate destructor and friendship to insure only factory can delete
protected:
	template<typename, typename> friend class AbstractSingletonFactory;	
	virtual ~NewClassBase()
	{
		std::cout << "Destroying NewClassBase @ " << this << std::endl;
	}
};

template<typename SCT, int SCID> class NewClassBaseSubclassBase :
	public NewClassBase,
	protected AbstractSingletonSubclass<int, NewClassBase, SCT, SCID>
{
};

class NewSubclass1 : public NewClassBaseSubclassBase<NewSubclass1, 1>
{
public:
	virtual int getId() { return 1; }
	
// boilerplate initialization stub to register with AbstractSingletonFactory
private:
	static InitAbstractSingletonSubclass _initStub;
};

NewSubclass1::InitAbstractSingletonSubclass NewSubclass1::_initStub;

class NewSubclass2 : public NewClassBaseSubclassBase<NewSubclass2, 2>
{
public:
	virtual int getId() { return 2; }
	
// boilerplate initialization stub to register with AbstractSingletonFactory
private:
	static InitAbstractSingletonSubclass _initStub;
};

NewSubclass2::InitAbstractSingletonSubclass NewSubclass2::_initStub;

static void TestNewBaseClass(AbstractSingletonFactory<int, NewClassBase> &abFactory)
{
	std::cout << std::endl
			  << "================================================================================"
			  << std::endl << std::endl
			  << "testing new base class..." <<
			  std::endl;
	
	for (int i = 1; i <= 2; i++)
	{
		NewClassBase *ncb = abFactory.getSingletonInstance(i);
	
		std::cout << "NCB[" << i << "] @ " << ncb << "; id=" << ncb->getId() << std::endl;
	}
}

int main(int argc, char **argv)
{
	AbstractSingletonFactory<int, NewClassBase> abFactory;
	
	TestNewBaseClass(abFactory);
}

A few things I don't like that I tried and tried to get rid of but it seems useless:

The boilerplate to register the class.... Any other better way to do this? I tried to encapsulate it all into the templates, it doesn't work...at the end of the day, it seems the static object to do the work needs to be created in the class.... I guess this is the flip of the prototype needing a dummy instance, I need this dummy static. Though, at least it's arguably sufficiently smaller.

The oddity with the GetDirectory stuff.... But, it seems better than more boilerplate to have to instantiate this member for each template type you use (or risk crash).

The "bridge" class (NewClassBaseSubclassBase) between the base and sub-classes to tie in the template. It's an empty template, so I'm hoping it could be optimized away, but...if anyone has some bright ideas (without macros) that would eliminate it, love to hear 'em.

Well...any comments would be much appreciated.

I attached the full source as a tar.gz if anyone is interested. It's a more comprehensive use of the templates, mostly for me to attempt to best insure it's working as expected. Hopefully, even if I don't get many comments, someone, someday, will find this useful, lol.

Thanks!

Last edited by DreamWarrior; 11-05-2012 at 05:20 PM..
# 2  
Old 11-05-2012
Whose requirements are these?
# 3  
Old 11-06-2012
Mine. Why?
Login or Register to Ask a Question

Previous Thread | Next Thread

7 More Discussions You Might Find Interesting

1. UNIX for Beginners Questions & Answers

AIX errpt : ( E7A89C7D Local adapter disabled after unstable singleton for long time )

Medel : 9117-MMC OS: AIX 6.1 Patch level : 6100-07-04-1216 Hacmp version : HACMP v 6.1.0.8 Oracle : 11.2.0.3 RAC Node : 2 node Dear, my one node server has been restarted early this morning, So, i tried to start HA and Oracle database. after that, the follow error appears at the node... (1 Reply)
Discussion started by: tomato00
1 Replies

2. Programming

Java Abstract Classes

Can anyone tell me if this is correct when creating classes in Java? public abstract class Animal { public class Point { public int x,y; } public class Animal { protected Point loc; protected String name; protected Random rng; String... (3 Replies)
Discussion started by: totoro125
3 Replies

3. Programming

C++ singleton

How to write a class that can only be instancialized once? what about my implementation below? #include<iostream> #include<stdexcept> using namespace std; class Singleton { public: int b; Singleton(); private: static int num; }; int Singleton::num = 1; (10 Replies)
Discussion started by: vistastar
10 Replies

4. Shell Programming and Scripting

abstract.sh

A highly abstract function invocation, just enjoy it ,guys! #!/bin/bash loop() { for((${1}=0; ${1}<${2}; ++${1})); do eval \$\{{3..12}\} done } numb() { echo -n "${!1}${!2}${!3} " (( ${3} == 2 )) && echo } eval loop" "{i..k}" 3" numb {i..k} (10 Replies)
Discussion started by: complex.invoke
10 Replies

5. Programming

What is singleton class ?

hello members, What is singleton class in c++ and in which case we will go with singleton class. Thanks & Regards Rajkumar_g (2 Replies)
Discussion started by: rajkumar_g
2 Replies

6. Programming

how abstract class differs in Java and C++?

hello all, i want to know if there is any difference in working and syntax declaration of abstract class in Java and C++. (1 Reply)
Discussion started by: haravivar
1 Replies

7. Programming

Compiling multiple cpp files (abstract factory pattern)

Hi all, I have been working with java for awhile and because of my school projects I needed to switch C++. I tried to implement some patterns in C++ but unfortunately I couldn't. Specifically, I tried to implement abstract factory pattern but since I used separated files (habitual behavior from... (4 Replies)
Discussion started by: SaTYR
4 Replies
Login or Register to Ask a Question