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)