Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Deciding which altenative library to use in code 1

Status
Not open for further replies.

Kalisto

Programmer
Feb 18, 2003
997
GB
In my code, I have 2 seperate data access classes, both of which inherit from an abstract base class (to ensure a uniform interface)

What I want to be able to do is to look at a registry setting, and from this see if the application is configured to use class a or b, and then create my data access class accordingly. At the moment I am including both headers in each file that might need data access, and and then in my code looking at the registry, and saying

if (value == FILE_BASED)
{create a file based access object)
else if
(value == DATA_BASED)
{create a data base object}

There has to be a better method than this, but the only other one I can think of is to compile 2 versions of my project, one for each method. (Which seems harder to maintain to me)

I am guessing that I might need to use dll's for this, but I dont know, so any help will be greatfully recieved !

K
 
>both of which inherit from an abstract base class (to ensure a uniform interface)

Wonderful!

>I am including both headers in each file ... There has to be a better method than this

Well, you'll still have to make a choice: Instantiate FileBased or DataBased
You can at least minimize it to one single if statement:

factory.h:
Code:
	class TheInterface;

	TheInterface* createClass(ValueType value);

factory.cpp:
Code:
	#include "factory.h"
	#include "FileBased.h"
	#include "DataBased.h"
	
	TheInterface* createClass(ValueType value)
	{
		TheInterface* p = 0:
		if (value == FILE_BASED)
			p =  new FileBased;
		else if (value == DATA_BASED)
			p =  new DataBased;
		else
		{
			ASSERT(FALSE);
		}

		return p;
	}


Only factory.cpp needs to see the xxxBased classes, all other just need the TheInterface:

Code:
  #include "TheInterface.h"
  #include "factory.h"
  ...
  TheInterface* c = createClass(...);
  c->Foo();
  ...

In the example above the factory is just a function, but you could of course make it more clever.
Perhaps a singleton class that when instantiated resolves and holds the registry info (ie will know for itself what 'value' is -> no parameter need to be passed to the create method).



/Per

"It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure."
 
Fantastic, and that saves me messing about with more dll's etc.

Cheers Perf.

K
 
Well, you can implement them in different DLL:s too if you wish, like one FileBased.dll and one DataBased.dll.

They'd both export the same interface (called factory.h above - but I guess there's a better name for it) with the createClass function or similar (naturally they only instantiate "their own" class).
At some initial point the client loads the specific DLL (see the AfxLoadLibrary function) depending on registry setting.

The client only "see" the factory.h and TheInterface.h and when it calls the createClass the loaded DLL (which ever it is) handles it.


/Per

"It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure."
 
Oh, another idea. The cools thing about OOP in this context is that not only can you minimize the occurances of if statements, but you can also minimize the number of times you have to make the comparison.

A factory class that returns the different instances, but only performs the if test once:

factory.h
Code:
class TheInterface;
class FactoryImplI; // Internal implementation class

class Factory
{
public:
	Factory();
	~Factory();

	TheInterface* createClass(); 

	// Its a singleton
	static Factory& getFactory();
	static void destroy();

private:
	static Factory* sInstance;
	FactoryImplI* mImpl;
};

factory.cpp
Code:
#include "factory.h"
#include "FileBased.h"
#include "DataBased.h"

Factory* Factory::sInstance = NULL;

class FactoryImplI
{
	public:
		FactoryImplI() {}
		virtual ~FactoryImplI() {};
		
		virtual TheInterface* createClass() = 0;		
};

class FactoryImplFile : public FactoryImplI
{
	public:
		FactoryImplFile():FactoryImplI() {}
		~FactoryImplFile() {}

		virtual TheInterface* createClass() { return new FileBased(); }
};

class FactoryImplData : public FactoryImplI
{
	public:
		FactoryImplFile():FactoryImplI() {}
		~FactoryImplFile() {}

		virtual TheInterface* createClass() { return new FileData(); }
};


//--------------------------------
Factory::Factory():mImpl(0)
{
	ValueType v = ResolveRegistryValue();
	if (v == FILE_BASED)
		mImpl = new FactoryImplFile();
	else if (v == DATA_BASED)
		mImpl = new FactoryImplData();
	else
	{
		ASSERT(FALSE); // Bug out
	}
}

Factory::~Factory()
{
	delete mImpl;
	mImpl = 0;
}

TheInterface* Factory::createClass() { return mImpl->createClass(); }

Factory* Factory::getFactory()
{
	if (sInstance == 0) 
		sInstance = new Factory();
	return sInstance;
}

void Factory::destroy()
{
	delete sInstance;
	sInstance = 0;
}

Only one if test performed no matter how many times you call the createClass method. From the client's perspective it is also quite easy to use:
Code:
	#include "Factory.h"
	#include "TheInterface.h"
    ...

	// First call will create the factory instance 
	// and resolve the registry flag and do the if test
	TheInterface* c1 = Factory::getFactory()->createClass();

	// 2nd call, factory is already created and 
	// test is alredy executed.
	TheInterface* c2 = Factory::getFactory()->createClass();

/Per

"It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure."
 
I think I see what your doing, I need to sit down with a cold beer and this printed out, to understand :p

Thanks, I'll see if I can make head nor tail of it.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top