diff options
-rw-r--r-- | libadhocutil/factory.h | 36 | ||||
-rw-r--r-- | libadhocutil/factory.impl.h | 25 | ||||
-rw-r--r-- | libadhocutil/unittests/Jamfile.jam | 10 | ||||
-rw-r--r-- | libadhocutil/unittests/testFactory.cpp | 65 |
4 files changed, 136 insertions, 0 deletions
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 <typename Base, typename ... Params> + class Factory { + public: + virtual ~Factory() = 0; + + virtual Base * create(const Params & ...) const = 0; + + template <typename Impl, typename _ = Factory<Base, Params...>> + 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<Implementation>, 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 <typename Base, typename ... Params> + Factory<Base, Params ...>::~Factory() = default; + + template <typename Base, typename ... Params> + const Factory<Base, Params...> * + Factory<Base, Params...>::get(const std::string & name) + { + return PluginManager::getDefault()->get<Factory>(name)->implementation(); + } + + template <typename Base, typename ... Params> + Base * + Factory<Base, Params...>::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 + : : : + <define>BOOST_TEST_DYN_LINK + <library>..//adhocutil + <library>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 <boost/test/unit_test.hpp> + +#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<BaseThing, int, std::string> 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<BaseThingFactory>("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); +} + |