#pragma once

#include <iostream>
#include <map>
#include <functional>

class Object {
public:
    virtual std::string ToString() const = 0;

    virtual ~Object() {}
};

class Apple : public Object {
public:
    std::string ToString() const override {
        return "apple!";
    }
};

class List : public Object {
public:
    std::string ToString() const override {
        return "list";
    }
};

class YetAnother : public Object {
public:
    std::string ToString() const override {
        return "yet another identifier";
    }
};

class Factory {
public:
    Object *Create(const std::string &class_id) {
        if (class_id == "apple!") {
            return new Apple;
        } else if (class_id == "list") {
            return new List;
        } else if (class_id == "yet another identifier") {
            return new YetAnother;
        } else {
            return classes_id[class_id]();
        }
    }

    void Register(const std::string &class_id, Object *(*instance_creator)()) {
        classes_id[class_id] = instance_creator;
    }

private:
    std::map<std::string, std::function<Object *()>> classes_id;
};