opm-core/opm/core/utility/Factory.hpp

175 lines
5.9 KiB
C++
Raw Normal View History

2011-10-07 03:54:25 -05:00
//===========================================================================
//
// File: Factory.hpp
//
// Created: Mon Nov 6 10:00:43 2000
//
// Author(s): Atgeirr F Rasmussen <atgeirr@sintef.no>
//
// $Date$
//
// $Revision$
//
//===========================================================================
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
2011-10-07 03:54:25 -05:00
OPM is free software: you can redistribute it and/or modify
2011-10-07 03:54:25 -05:00
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
2011-10-07 03:54:25 -05:00
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
2011-10-07 03:54:25 -05:00
*/
#ifndef OPM_FACTORY_HEADER
#define OPM_FACTORY_HEADER
2011-10-07 03:54:25 -05:00
#include <opm/core/utility/ErrorMacros.hpp>
2011-10-07 03:54:25 -05:00
#include <map>
#include <memory>
2011-10-07 03:54:25 -05:00
namespace Opm
2011-10-07 03:54:25 -05:00
{
2012-06-19 17:04:48 -05:00
2011-10-07 03:54:25 -05:00
/** This is an object factory for creating objects of some type
* requested by the user, with a shared base class. The user
* need only interact with the factory through the static
* template member addCreator() and the static member function
* createObject().
*/
2012-06-19 17:04:48 -05:00
template<class Base>
2011-10-07 03:54:25 -05:00
class Factory
{
public:
/// The type of pointer returned by createObject().
typedef std::shared_ptr<Base> ProductPtr;
2011-10-07 03:54:25 -05:00
2012-06-19 17:04:48 -05:00
/// Creates a new object of the class associated with the given type string,
2011-10-07 03:54:25 -05:00
/// and returns a pointer to it.
2012-06-19 17:04:48 -05:00
/// \param type the type string of the class that the user wants to have
/// constructed.
2011-10-07 03:54:25 -05:00
/// \return (smart) pointer to the created object.
2012-06-19 17:04:48 -05:00
static ProductPtr createObject(const std::string& type)
{
return instance().doCreateObject(type);
}
2011-10-07 03:54:25 -05:00
2012-06-19 17:04:48 -05:00
/// Clones an new object of the class associated with the given type string,
2012-06-07 08:08:01 -05:00
/// and returns a pointer to it.
2012-06-19 17:04:48 -05:00
/// \param type the type string of the class that the user wants to have
/// constructed.
/// \param original (smart) pointer to object to be cloned.
2012-06-07 08:08:01 -05:00
/// \return (smart) pointer to the created object.
2012-06-19 17:04:48 -05:00
static ProductPtr cloneObject(const std::string& type,
2012-06-07 08:08:01 -05:00
const ProductPtr original)
2012-06-19 17:04:48 -05:00
{
return instance().doCloneObject(type, original);
}
2012-06-07 08:08:01 -05:00
2012-06-19 17:04:48 -05:00
/// Add a creator to the Factory.
2011-10-07 03:54:25 -05:00
/// After the call, the user may obtain new objects of the Derived type by
/// calling createObject() with the given type string as an argument.
/// \tparam Derived the class we want to add a creator for, must inherit
/// the class template parameter Base.
2012-06-19 17:04:48 -05:00
/// \param type the type string with which we want the Factory to associate
/// the class Derived.
template<class Derived>
static void addCreator(const std::string& type)
{
instance().template doAddCreator<Derived>(type);
2012-06-19 17:04:48 -05:00
}
2011-10-07 03:54:25 -05:00
private:
// The method that implements the singleton pattern,
// using the Meyers singleton technique.
2012-06-19 17:04:48 -05:00
static Factory& instance()
{
2011-10-07 03:54:25 -05:00
static Factory singleton;
2012-06-19 17:04:48 -05:00
return singleton;
}
2011-10-07 03:54:25 -05:00
2012-06-19 17:04:48 -05:00
// Private constructor, to keep users from creating a Factory.
Factory()
{
}
2011-10-07 03:54:25 -05:00
// Abstract base class for Creators.
class Creator
{
public:
virtual ProductPtr create() = 0;
2012-06-07 08:08:01 -05:00
virtual ProductPtr clone(ProductPtr original) = 0;
2011-10-07 03:54:25 -05:00
virtual ~Creator() {}
};
/// This is the concrete Creator subclass for generating Derived objects.
2012-06-19 17:04:48 -05:00
template<class Derived>
class ConcreteCreator: public Creator
2011-10-07 03:54:25 -05:00
{
public:
virtual ProductPtr create()
{
return ProductPtr(new Derived);
}
2012-06-07 08:08:01 -05:00
virtual ProductPtr clone(const ProductPtr original)
{
const Derived& orig = dynamic_cast<const Derived&>(*original);
return ProductPtr(new Derived(orig));
}
2011-10-07 03:54:25 -05:00
};
typedef std::shared_ptr<Creator> CreatorPtr;
2011-10-07 03:54:25 -05:00
typedef std::map<std::string, CreatorPtr> CreatorMap;
// This map contains the whole factory, i.e. all the Creators.
2012-06-19 17:04:48 -05:00
CreatorMap string_to_creator_;
2011-10-07 03:54:25 -05:00
// Actually creates the product object.
2012-06-19 17:04:48 -05:00
ProductPtr doCreateObject(const std::string& type)
{
typename CreatorMap::iterator it;
it = string_to_creator_.find(type);
if (it == string_to_creator_.end()) {
2013-08-28 06:59:03 -05:00
OPM_THROW(std::runtime_error, "Creator type " << type
2012-06-19 17:04:48 -05:00
<< " is not registered in the factory.");
}
return it->second->create();
}
2011-10-07 03:54:25 -05:00
2012-06-07 08:08:01 -05:00
// Actually clones the product object.
2012-06-19 17:04:48 -05:00
ProductPtr doCloneObject(const std::string& type,
2012-06-07 08:08:01 -05:00
const ProductPtr original)
2012-06-19 17:04:48 -05:00
{
typename CreatorMap::iterator it;
it = string_to_creator_.find(type);
if (it == string_to_creator_.end()) {
2013-08-28 06:59:03 -05:00
OPM_THROW(std::runtime_error, "Creator type " << type
2012-06-19 17:04:48 -05:00
<< " is not registered in the factory.");
}
return it->second->clone(original);
}
2012-06-07 08:08:01 -05:00
2011-10-07 03:54:25 -05:00
// Actually adds the creator.
2012-06-19 17:04:48 -05:00
template<class Derived>
2011-10-07 03:54:25 -05:00
void doAddCreator(const std::string& type)
{
CreatorPtr c(new ConcreteCreator<Derived>);
2012-06-19 17:04:48 -05:00
string_to_creator_[type] = c;
2011-10-07 03:54:25 -05:00
}
};
} // namespace Opm
2011-10-07 03:54:25 -05:00
#endif // OPM_FACTORY_HEADER