I'm trying to understand the abstract factory pattern, here is my first approximation:
#include <iostream>
using namespace std;
class Soldier
{
public:
virtual void shoot()=0;
};
class Archer: public Soldier
{
public:
void shoot(){
cout<<"Archer shoot"<<endl;
}
};
class Rider: public Soldier
{
public:
void shoot(){
cout<<"Rider shoot"<<endl;
}
};
class AbstractFactory
{
public:
virtual Soldier* createArcher()=0;
virtual Soldier* createRider()=0;
};
class OrcFactory: public AbstractFactory
{
Soldier* createArcher()
{
return new Archer();
};
Soldier* createRider()
{
return new Rider();
};
};
class HumanFactory: public AbstractFactory
{
Soldier* createArcher()
{
return new Archer();
};
Soldier* createRider()
{
return new Rider();
};
};
class Game
{
public:
AbstractFactory* factory;
Game(AbstractFactory* factory):factory(factory){};
};
int main()
{
Game* game = new Game(new HumanFactory);
Archer* HumanArcher = static_cast <Archer*>(game->factory->createArcher());
Rider* humanRider = static_cast <Rider*>(game->factory->createRider());
HumanArcher->shoot();
humanRider->shoot();
return 0;
}
This is what I want to reproduce:
I have experience in programing but I'm newbie with patterns, not sure if this is the optimal solution or even if it's a good solution.
I'm reading about game engine architecture, but I'm stuck in this, not by errors, just doubt about the right solution for this exercise. The book has basic examples but not enough to understand it at all.
That's not exactly what makes an abstract factory. In your case, you would need a structure like this (the diagram ended up a bit too big, click the image to see it at its original resolution):
The idea is that you have a family of abstract classes or interfaces (here the units, archer, rider, etc.) and a family of concrete implementations for each type of factory (implementations for humans, implementations for orcs, etc.). The game uses only the abstract factory interface and does not need to care which are the actual types, while each implementation only needs to provide its own behaviour, allowing for easy extension.
As a side note, I used covariant return types in the diagram because C++ supports it (as opposed to, for example, C#) and it seems to make sense in this case (e.g. the method makeArcher
in the base factory interface SoldierFactory
is declared to return an Archer
object, but the same method in OrcSoldierFactory
returns a OrcArcher
), but that is not strictly required by the pattern.