0

I am writing a generic factory class called Factory

//abstract factory
template <class C>
class Factory{
    public:
        virtual C* create()=0;
}
//concrete factory
template <class C>
class NormalFactory:public Factory<C>{
    public:

    C* create(){return new C;}
}

I want to do the following:

typedef Factory<Enemy> EnemyFactory;
EnemyFactory* e = new NormalFactory<Troll>; //Troll inherits Enemy
//client code
Enemy* enemy = e->create();

But unfortunately I can't do that since NormalFactory does not inherit Factory. Is there a way around that to accomplish what I wanted to?

(implementing an abstracted EnemyFactory without knowing the actual type of Enemy it create())

Han_Chen
  • 195
  • 2
  • 14
  • This is a *Parallel Inheritance Hierarchies* problem (considered bay many as *code smell*). You might want to lookup some (Java) Design Patterns like [Visitor](http://stackoverflow.com/questions/696350/avoiding-parallel-inheritance-hierarchies). As an application to games, see [Game Programming Patterns](http://gameprogrammingpatterns.com/contents.html) by Robert Nystrom (EA). Specifically, "Prototype" pattern. Also, you should consider a possibility that you are going wrong way with all this object-oriented stuff. – Ivan Aksamentov - Drop Jan 02 '16 at 01:53

2 Answers2

1

A simple technical solution is to parameterise the concrete factory with the desired base, like this:

template <class C, class C_base = C>
class NormalFactory:public Factory<C_base>{
    public:

    C* create(){return new C;}
};

Example at Coliru.

However, the design doesn't feel right somehow. I suggest thinking about what the factories are meant to accomplish, and if there's any other more natural way of accomplishing that in C++. I.e., I think this is an XY-question.

Community
  • 1
  • 1
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • The main goal here is to encapsulate object creation. I have a class that is responsible for generating a `Map` that contains `Enemy`, but it does not need to know which type of `Enemy` it is, only that it is `Enemy` type. Also, it is responsible for putting `Treasure` and `Potion` on the map which are all polymorphic types. I think this works for now, I can't think of a way to work around this. – Han_Chen Jan 02 '16 at 20:05
0

You can templatize create so that you say what type of enemy it will create.

template<class T>
T * create() {
    return new T;
}

Enemy * e = my_normal_factory.create<Troll>();

In which case there's no need to templatize the class.

or this

//abstract factory
class Factory{
    public:
        virtual Enemy * create()=0;
}
//concrete factory
template <class C>
class NormalFactory:public Factory<C>{
    public:

    Enemy* create(){return new C;}
}


Factory* e = new NormalFactory<Troll>; //Troll inherits Enemy


void some_function(Factory & somefactory) {
    Enemy* enemy = somefactory->create();
}

some_function(e);
xaxxon
  • 19,189
  • 5
  • 50
  • 80
  • I thought of that, but the problem is that I need to pass `Factory` object containing the information about which type of `Enemy` it creates. I can't have client code knowing which type of `Enemy` it creates, it only calls `create()` – Han_Chen Jan 02 '16 at 20:37
  • why not just Enemy* create(){return new C;} then? change the base class as well and make it not a template. that way theres a known base type – xaxxon Jan 02 '16 at 22:46
  • Yeah... then I can't do stuff like `typedef Factory TreasureFactory` then `TreasureFactory* tf = new NormalFactory;` – Han_Chen Jan 05 '16 at 06:25