Я пытаюсь понять абстрактный шаблон фабрики, вот мое первое приближение:
#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;
}
Это то, что я хочу воспроизвести:
У меня есть опыт программирования, но я новичок с шаблонами, не уверен, что это оптимальное решение или даже хорошее решение.
Я читаю об архитектуре игрового движка, но я застрял в этом, не из-за ошибок, просто сомневаюсь в правильном решении для этого упражнения. В книге есть основные примеры, но их недостаточно, чтобы понять это.
Это не совсем то, что делает абстрактная фабрика. В вашем случае вам понадобится такая структура (диаграмма оказалась слишком большой, щелкните изображение, чтобы увидеть его в исходном разрешении):
Идея состоит в том, что у вас есть семейство абстрактных классов или интерфейсов (здесь — unit, archer, rider и т. Д.) И семейство конкретных реализаций для каждого типа фабрики (реализации для людей, реализации для орков и т. Д.). В игре используется только абстрактный интерфейс фабрики, и не нужно заботиться о том, какие типы являются действительными, в то время как каждая реализация должна обеспечивать только свое поведение, что позволяет легко расширять ее.
В качестве примечания я использовал ковариантные типы возврата в диаграмме, потому что C ++ поддерживает это (в отличие, например, от C #), и, кажется, имеет смысл в этом случае (например, метод makeArcher
в базовом заводском интерфейсе SoldierFactory
объявлено о возвращении Archer
объект, но тот же метод в OrcSoldierFactory
возвращает OrcArcher
), но это не является обязательным требованием шаблона.
Других решений пока нет …