I'm implementing an abstract factory pattern (in c++), but there is a slight problem.
I'd like to avoid creating a place which must know at compile time what factories exist.
Usually in the examples I see something like this.
Factory * getFactory()
{
if(/*we should make factoryA*/)
{
return FactoryA::instance();
}
else if(/*we should return FactoryB*/)
{
return FactoryB::instance();
}
else
{
return NULL;
}
}
I could do something like this, but I want better!
What I have in mind is that the Factory base class would have a list of Factories, each class inherited from Factory would create a static instance and add that instance to the list, through a pr开发者_JS百科otected class function in Factory.
However, I can't figure out a way to do this without playing Russian Roulette with static object initialization.
To avoid problems with static initialization order, you can make the list a static member of a function getFactoryList(). This will then ensure that the list exists when the protected constructor needs to add a factory to the list.
You'll then want to add a virtual method to Factory to determine if a given factory should be used. Hopefully only one factory is eligible for use at a time, so that the order that the factories got created does not change which factory is returned.
Somthing Simple:
class BaseFactory
{
public:
BaseFactory()
{
std::list<BaseFactory*>& fList = getFactoryList();
fList.push_back(this);
// If you are feeling brave.
// Write the destructor to remove the object from the list.
//
// Note C++ guarantees the list will live longer than any of the factories
// Because the list will always be completely constructed before any
// of the factory objects (because we get the list in the constructor).
}
static BaseFactory& getFactory() // Don't return a pointer (use a reference)
{
std::list<BaseFactory*>& fList = getFactoryList();
std::list<BaseFactory*>::iterator i = selectFactory(fList);
if (i == fList.end()
{
static FakeFactory fakeFactory; // Having a fake factory that
// that returns fake object
// is usually a lot easier than checking for
// NULL factory objects everywhere in the code
//
// Alternatively throw an exception.
return fakeFactory;
}
return *(*i); // return reference
}
private:
static std::list<BaseFactory*>& getFactoryList()
{
static std::list<BaseFactory*> factoryList; // Notice the static
return factoryList;
}
};
How would you benefit form such design? I mean, even when you had that list, you would have to select that factory somehow, based on some criteria.
Try Inversion Of Control pattern instead.
If Class A needs to create an object, pass factory to that class.
class A {
Factory *f;
public:
A(Factory *f)
: f(f)
{ }
void doSomething()
{
Object o = f->produce();
...
}
}
Then you would decide which factory to use on the "higher level". Factory may came form the source, form plugin etc.
I use a pattern to collect instances of subclasses. This is the bare bones of it couched in terms of a factory:
class Factory {
public:
virtual Foo* makeFoo()=0;
...
protected:
Factory(){
getFactoryList().push_back(this);
}
private:
FactoryList& getFactoryList(); // Returns static list
};
class FactoryA: public Factory{
Foo* makeFoo(); // I make a Foo my way
} FACTORYINSTANCE;
You still need a way of searching the list for the correct factory to use, and my macro FACTORYINSTANCE just evaluates to a unique name in order to invoke its own constructor.
精彩评论