3

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:

class diagram

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.

Melebius
  • 6,183
  • 4
  • 39
  • 52
Gustavo Otero
  • 91
  • 2
  • 11
  • 5
    Maybe Code Review would be a better place to ask this question. – dandan78 Jan 15 '18 at 11:01
  • It would make more sense if Soldier's properties was set differently between Orc and human. – Jarod42 Jan 15 '18 at 11:02
  • @dandan78 I'm not so sure, this looks like an exercise in hypothetical scenario's, something Code Review [doesn't handle well](https://codereview.stackexchange.com/help/dont-ask). This is definitely not code used in production, it isn't doing anything useful at all. – Mast Jan 15 '18 at 11:11
  • 2
    You might be interested in [wizards and warriors](https://ericlippert.com/2015/04/27/wizards-and-warriors-part-one/). Although using C# examples, it shows why game rules make bad language rules for OOP languages. – nvoigt Jan 15 '18 at 11:22
  • Possible duplicate of https://stackoverflow.com/questions/1001767/what-is-the-basic-difference-between-the-factory-and-abstract-factory-patterns and https://stackoverflow.com/questions/5739611/differences-between-abstract-factory-pattern-and-factory-method – Ælex Jan 15 '18 at 12:09
  • 2
    I don't think it's off-topic, the OP is having trouble understanding and implementing a design pattern for a particular case, not asking about the quality of his implementation, and I don't think it's a dupe of factory vs abstract factory questions... – jdehesa Jan 15 '18 at 12:22
  • Yes, is an exercise , not a real project in production. – Gustavo Otero Jan 16 '18 at 06:18

1 Answers1

7

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):

Abstract factory pattern

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.

jdehesa
  • 58,456
  • 7
  • 77
  • 121