From 13ef5b22effca60ac26bce71d4c67011d4c533aa Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 14 Sep 2015 20:31:30 +0100 Subject: Add basic factory support --- libadhocutil/factory.h | 36 +++++++++++++++++++ libadhocutil/factory.impl.h | 25 +++++++++++++ libadhocutil/unittests/Jamfile.jam | 10 ++++++ libadhocutil/unittests/testFactory.cpp | 65 ++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 libadhocutil/factory.h create mode 100644 libadhocutil/factory.impl.h create mode 100644 libadhocutil/unittests/testFactory.cpp diff --git a/libadhocutil/factory.h b/libadhocutil/factory.h new file mode 100644 index 0000000..2493525 --- /dev/null +++ b/libadhocutil/factory.h @@ -0,0 +1,36 @@ +#ifndef ADHOCUTIL_FACTORY_H +#define ADHOCUTIL_FACTORY_H + +#include "plugins.h" + +namespace AdHoc { + template + class Factory { + public: + virtual ~Factory() = 0; + + virtual Base * create(const Params & ...) const = 0; + + template > + class For : public _ + { + public: + Base * create(const Params & ... p) const override + { + return new Impl(p...); + } + }; + + static const Factory * get(const std::string & name); + static Base * create(const std::string & name, const Params & ... p); + }; +} + +#define NAMEDFACTORY(Name, Implementation, BaseFactory) \ + NAMEDPLUGIN(Name, BaseFactory::For, BaseFactory) + +#define FACTORY(Implementation, BaseFactory) \ + NAMEDFACTORY(#Implementation, Implementation, BaseFactory) + +#endif + diff --git a/libadhocutil/factory.impl.h b/libadhocutil/factory.impl.h new file mode 100644 index 0000000..4e34310 --- /dev/null +++ b/libadhocutil/factory.impl.h @@ -0,0 +1,25 @@ +#ifndef ADHOCUTIL_FACTORY_IMPL_H +#define ADHOCUTIL_FACTORY_IMPL_H + +#include "factory.h" + +namespace AdHoc { + template + Factory::~Factory() = default; + + template + const Factory * + Factory::get(const std::string & name) + { + return PluginManager::getDefault()->get(name)->implementation(); + } + + template + Base * + Factory::create(const std::string & name, const Params & ... p) + { + return get(name)->create(p...); + } +} +#endif + diff --git a/libadhocutil/unittests/Jamfile.jam b/libadhocutil/unittests/Jamfile.jam index 77aede4..ecee7d1 100644 --- a/libadhocutil/unittests/Jamfile.jam +++ b/libadhocutil/unittests/Jamfile.jam @@ -129,3 +129,13 @@ run testPlugins ; +run + testFactory.cpp + : : : + BOOST_TEST_DYN_LINK + ..//adhocutil + boost_utf + : + testFactory + ; + diff --git a/libadhocutil/unittests/testFactory.cpp b/libadhocutil/unittests/testFactory.cpp new file mode 100644 index 0000000..9b463f1 --- /dev/null +++ b/libadhocutil/unittests/testFactory.cpp @@ -0,0 +1,65 @@ +#define BOOST_TEST_MODULE Factory +#include + +#include "factory.h" +#include "factory.impl.h" +#include "plugins.h" +#include "plugins.impl.h" + +using namespace AdHoc; + +class BaseThing { + public: + BaseThing(int, const std::string &){} + + virtual void execute() const = 0; +}; + +class ImplOfThing : public BaseThing { + public: + ImplOfThing(int i, const std::string & s) : BaseThing(i, s) {} + void execute() const { } +}; +class OtherImplOfThing : public BaseThing { + public: + OtherImplOfThing(int i, const std::string & s) : BaseThing(i, s) {} + void execute() const { } +}; + +typedef AdHoc::Factory BaseThingFactory; + +NAMEDFACTORY("a", ImplOfThing, BaseThingFactory); +FACTORY(OtherImplOfThing, BaseThingFactory); + +BOOST_AUTO_TEST_CASE( ready ) +{ + BOOST_REQUIRE_EQUAL(2, PluginManager::getDefault()->count()); +} + +BOOST_AUTO_TEST_CASE( get ) +{ + auto all = PluginManager::getDefault()->getAll(); + auto factory1 = PluginManager::getDefault()->get("a")->implementation(); + auto factory2 = BaseThingFactory::get("a"); + auto factory3 = BaseThingFactory::get("OtherImplOfThing"); + BOOST_REQUIRE(factory1); + BOOST_REQUIRE_EQUAL(factory1, factory2); + BOOST_REQUIRE(factory3); + BOOST_REQUIRE(factory1 != factory3); +} + +BOOST_AUTO_TEST_CASE( create ) +{ + auto factory1 = BaseThingFactory::get("a"); + auto factory2 = BaseThingFactory::get("OtherImplOfThing"); + auto i1 = factory1->create(1, "std"); + auto i2 = factory1->create(1, "std"); + auto i3 = factory2->create(1, "std"); + BOOST_REQUIRE(i1); + BOOST_REQUIRE(i2); + BOOST_REQUIRE(i3); + BOOST_REQUIRE(i1 != i2); + BOOST_REQUIRE(i1 != i3); + BOOST_REQUIRE(i2 != i3); +} + -- cgit v1.2.3