#pragma once

#include <map>
#include <string>

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

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

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

class Another : public Object {
 public:
  std::string ToString() const override {
    return "yet another identifier";
  }
  static Object *Create() {
    return new Another;
  }
};

class Factory {
 public:
  Factory() {
    methods["apple!"] = Apple::Create;
    methods["list"] = List::Create;
    methods["yet another identifier"] = Another::Create;
  }
  Object *Create(const std::string &class_id) {
    auto it = methods.find(class_id);
    return it->second();
  }

  void Register(const std::string &class_id, Object *(*instance_creator)()) {
    auto it = methods.find(class_id);
    if (it == methods.end()) {
      methods[class_id] = *instance_creator;
    }
  }

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