Object Factory question

Started by
10 comments, last by Antheus 15 years, 8 months ago
So I understand object factories and how to use them when the class hierarchy is one layer deep. But how can you use a factory for objects that are 2+ levels deep? Below is an example:

Class Animal
{
    void attack() = 0;
};

Class Cat : public Animal
{
    void attack() = 0;
    void meow() = 0;
};

Class Dog : public Animal
{
    void attack() = 0;
    void bark() = 0;
};

Class ConcreteCat
{
    //implementation of abstract Cat
};

Class ConcreteDog
{
    //implementation of abstract Dog
};


So now I want an Animal factory...do I need to have separate factories, one for cats and one for dogs? Is it good/bad to have an Animal factory and then have to cast the Animal* to a Cat* or Dog*? Thanks in advance!
Advertisement
You would need to identify each concrete type separately, and then have your factory switch on the specific one you want to create. The depth of the hierarchy shouldn't matter, unless you want to have a factory function at each level that calls yet another factory function, etc. But something like this works just fine:

Animal* IWantMyselfAnAnimal(int id){   switch(id)   {      case DOG:         return new ConcreteDog();      case CAT:         return new ConcreteCat();      default:         message("While probably tasty, not what I was expecting!");         return NULL;   }}
So in your example, your factory returns an Animal*...so what if I have a piece of code that needs to create a ConcreteCat and make the cat meow? Do I have to cast like this:

Cat* pCat = dynamic_cast<Cat*>( IWantMyselfAnAnimal(CAT) );pCat->meow();
There are different ways to build factories and it partially depends on what it is you actually want. Your example somewhat lacks a real problem which makes suggesting the right solution tricky.

Zipster's factory is an Animal factory. There'd be little reason to cast the Animal* to anything else; if you knew you wanted a dog or cat you'd just do:

ConcreteDog dog; //or
ConcreteCat cat;
Specifically, this is for a plugin system...so I have an abstract Plugin interface, then abstract saving/loading plugins, and abstract renderer plugin, etc. I then have concrete saving/loading plugins, and concrete renderer plugins...
In that case a PluginFactory is probably not going to do you much good when you consider how different the configuration of a renderering module is from a serialisation module.

If working with that design I would have factory functions like createRenderer and so on - so that is to have factories for the more specialised classes rather than the most generalised class.
That's what I was wondering...thanks dmatter!

So is it true that in general, factories have to be for one 'level' up on the class hierarchy (or actually, for whatever interface you need to work with)?
Quote:Original post by SAE Superman
So is it true that in general, factories have to be for one 'level' up on the class hierarchy (or actually, for whatever interface you need to work with)?
I'm not sure I'd say it's a rule of thumb to be honest. You certainly could have a plugin-factory if you actually were just interested in interacting through just the plugin interface. Also factories can have an inheritance hierarchy all of their own; you can subclass your factories from other factories which in some ways would botch a generalisation like they must be one 'level' up.

Concerns about where to 'place' a factory along the inheritance chain of it's products are uncommon these days fortunately. In modern C++ programming inheritance hierarchies have become shallow anyway, seldom needing more than, say, one level of inheritance. Things are much more obvious and easier to manage that way. In regards to this, what does your Plugin base class actually do?
My high level plugin interface basically just has naming and versioning information...just stuff that every plugin has to have... Is there a way to flatten the hierarchy in an elegant way?
It depends really, composition (has-a something) is usually cited as being favourable to inheritance (is-a something). I can certainly make an easy example use of it for plugins - though I'm obviously not familiar with your actual system to know if it would work for you.

Ex:

// Just the interface because I'm lazyclass PluginDescription{    PluginDescription(const std::string & n, const std::string & v);    const std::string & name();    const std::string & version();};// Then each plugin module will be composed using thatclass Renderer{public:    const PluginDescription & plugin() { return pd; }protected:    Renderer(const PluginDescription & pd) : pd(pd) { }private:    const PluginDescription pd;};

As you can see composition usually requires more 'leg work' to get it going but when you put together larger system it leads more elegant designs.

In this case I can see reasons for and against inheritance (is-a plugin) versus composition (has-a plugin name/version). I can't see there being much harm to either option here either. If you need to treat all plugins the same for some reason then inheritance might be the way to go, like storing a collection of all plugins regardless of what they are - cannot think of a reason to do that here though what with your plugins being essentially whole subsystems (surely you'll always have a renderer and it's just a matter of choosing which renderer?)

This topic is closed to new replies.

Advertisement