Base class for an object factory.
This class implements the actual factory. The type of the factory class would be something like Async::Factory<Animal> for a base class representing animals. It is most often adviced to create a typedef to represent the type of the factory, e.g.:
Creating a typedef bocomes incresingly convenient when the constructor of the objects being manufactured take one or more arguments since the type definition will become quite long.
Also the addition of a convenience function for creating objects make the usage of the factory easier and more readable. This function make use of the typedef declared above and also rely on that a convenience struct for the specific factories have been declared as described for Async::SpecificFactory.
The following example will describe in more detail how to use the factory classes.
#include <iostream>
#include <memory>
class Animal
{
public:
Animal(const std::string& given_name) : m_given_name(given_name) {}
virtual ~Animal(void) {}
const std::string& givenName(void) const { return m_given_name; }
virtual const char* say(void) const = 0;
private:
std::string m_given_name;
};
struct Dog : public Animal
{
static constexpr auto OBJNAME = "dog";
Dog(const std::string& given_name) : Animal(given_name) {}
virtual const char* say(void) const override { return "Voff"; }
};
struct Cat : public Animal
{
static constexpr auto OBJNAME = "cat";
Cat(const std::string& given_name) : Animal(given_name) {}
virtual const char* say(void) const override { return "Meow"; }
};
struct Fox : public Animal
{
static constexpr auto OBJNAME = "fox";
Fox(const std::string& given_name) : Animal(given_name) {}
virtual const char* say(void) const override
{
return "Ding, ding, ding, ding, ding, di-ding, di-ding";
}
};
struct Cow : public Animal
{
static constexpr auto OBJNAME = "cow";
Cow(const std::string& given_name) : Animal(given_name) {}
virtual const char* say(void) const override
{
return "Moooo";
}
};
template <class T>
struct AnimalSpecificFactory
{
AnimalSpecificFactory(void)
:
Async::SpecificFactory<Animal, T, std::string>(T::OBJNAME) {}
};
std::unique_ptr<Animal> createAnimal(const std::string& obj_name,
const std::string& animal_name)
{
static AnimalSpecificFactory<Dog> dog_factory;
static AnimalSpecificFactory<Cat> cat_factory;
static AnimalSpecificFactory<Fox> fox_factory;
return std::unique_ptr<Animal>(
AnimalFactory::createNamedObject(obj_name, animal_name));
}
int main(int argc, const char *argv[])
{
if (argc < 3)
{
std::cout << "Usage: " << argv[0] << " <obj name> <given name>"
<< std::endl;
return 1;
}
const std::string obj_name(argv[1]);
const std::string given_name(argv[2]);
AnimalSpecificFactory<Cow> cow_factory;
auto obj = createAnimal(obj_name, given_name);
if (obj == nullptr)
{
std::cout << "Sorry, but there is no animal \"" << argv[1] << "\" :-("
<< std::endl;
std::cout << "Valid animals: " << AnimalFactory::validFactories()
<< std::endl;
exit(1);
}
std::cout << "- Hello, " << obj->givenName() << "! What do you say?\n- "
<< obj->say() << "!" << std::endl;
}
Some templates used to support the creation of an object factory.
Namespace for the asynchronous programming classes.