Factory

We would want to write a tool that can provide similar functionality between components with different implementations. It should be easily expandable with new components that doesn't require to change anything in the main app.

For this task we are going to use a factory pattern.

Interface

AbstractTime.h

class AbstractTime {
public:
    virtual AbstractTime* build() = 0;
    virtual std::time_t get() const = 0;
    virtual void set(std::time_t time) = 0;
    virtual std::string name() const = 0;
};

Factory

Factory itself will be a singleton. And essentially it's a collection of build functions. And we will be calling register_builder in an interesting way (check for constructors in concrete objects).

TimeFactory.h

using BuildFunction = std::function<AbstractTime*()>;

class TimeFactory {
public:
    static TimeFactory* instance() {
        if (!factory) {
            factory = new TimeFactory();
        }
        return factory;
    }
    static void register_builder(const BuildFunction& builder) {
        builders.push_back(builder);
    }
    static std::vector<BuildFunction>::iterator iterator_begin() {
        return builders.begin();
    }
    static std::vector<BuildFunction>::iterator iterator_end() {
        return builders.end();
    }
private:
    static TimeFactory* factory;
    static std::vector<BuildFunction> builders;
};

TimeFactory.cpp

#include "TimeFactory.h"

TimeFactory* TimeFactory::factory = nullptr;
std::vector<BuildFunction> TimeFactory::builders = std::vector<BuildFunction>();

Define components

Implement the interface

class MotherboardRTC : public AbstractTime {
public:
    MotherboardRTC() {
        TimeFactory::register_builder(std::bind(&MotherboardRTC::build, this));
    }
    AbstractTime* build() override {
        return this;
    }

And now just define a stati object. But this line actually calls register_builder in a static object of TimeFactory class. So this object will be available in the main function.

static MotherboardRTC motherboard_rtc;

Use components

    std::map<std::string, AbstractTime*> loaded_time;
    for (auto i = TimeFactory::iterator_begin(); i != TimeFactory::iterator_end(); ++i) {
        auto build_function = *i;
        auto time = build_function();
        loaded_time[time->name()] = time;
    }

Result

./time_factory list
# random
# system

./time_factory get system
# system: 08/26/24 20:43:02 Pacifique (heure dТete)