Sign in to follow this  
Dragon_Strike

Unity my abstract factory

Recommended Posts

Dragon_Strike    264
well for once ive tried to create a somewhat serios implementation of something like the abstract factory design pattern for my 3d engine... im fairly satisfied with it and i cant think of anything more that needs to be added or modified... i was hoping u guys took a look at it and tell me if ive missed something or i could improve it in any way... thx
/********************************************************
     This source file is part of "Drone", graphics engine, www.droneworks.net
     Copyright (c) 2008 By Robert Nagy

     Permission to use, copy, modify, this code may be used for non commericial use without fee, 
     provided that the above copyright notice appear in all copies and that both that copyright 
     notice and this permission notice appear in supporting documentation.

     Many thanks to the www.gamedev.net community.
********************************************************/

/********************************************************
     AbstractFactory.h

     Implements an abstract interface for creating managed instances of multiple types. 

     Example:

     typedef Factory<mpl::vector<Texture, Buffer>> ResourceFactory;
     shared_ptr<Texture> diffuse1 = manager->Register<Texture>("diffuse1", "filepath.tga", TEXTURE_2D );
********************************************************/

#pragma once

#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>

#include <boost/mpl/vector.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/inherit_linearly.hpp>
#include <boost/mpl/inherit.hpp>

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/variant.hpp>

#include <map>
#include <string>
#include <vector>

namespace drone
{
namespace base
{

/********************************************************************************
     FactoryUnit
     A single Factory for creating managed instances of a single types.
********************************************************************************/

template <class Product, typename IdentifierType = boost::variant<std::string, int>>
class FactoryUnit
{
public:
	typedef boost::shared_ptr<Product>	ProductPtr;
	typedef IdentifierType IDType;

     // Removes the pointer reference in the associaton list
     // note: since pointers are stored as an reference counted shared_ptr
     //       the instance will live on outside of the class until there
     //       are no other references. Thus we don't have to do reference count.
	bool Unregister(const IDType& id)
	{		
		return associations_.erase(id) == 1;
	}

     // Return a pointer to the instance specified by id, if it does not exists create a new
     // instance with the passed functor, "creator".
	ProductPtr Register(const IDType& id, boost::function<ProductPtr ()> creator )
	{	
		ProductPtr product = Find(id);

		if (!product)	
		{
               try
               {
			     product = creator();
                    associations_.insert(AssocMap::value_type(id, product)).second;
               }
               catch(...)
               {
                    associations_.erase(id);
                    product.reset();
                    throw "FactoryUnit: Failed to register product.";  
               }
                    
		} 

		return product;
	}

     // Return a pointer to the instance specified by id, if it does not exists return a null pointer.
	ProductPtr Find(const IDType& id)
	{
		typename AssocMap::const_iterator i = associations_.find(id);
		if (i != associations_.end())		
			return (i->second);		

		return ProductPtr();
	}

	void Clear()
	{
		associations_.clear();
	}

	Product* prototype;
private:
     typedef std::map<IDType, ProductPtr> AssocMap;
     AssocMap associations_;	
	
};

/********************************************************************************
     AbstractFactory
     Factory container interface defined by a mpl::vector<>.
********************************************************************************/

namespace mpl = boost::mpl;

// Inherit all FactoryUnit types defined in TList
template<class TList, class IdentifierType>
class AbstractFactory : public mpl::inherit_linearly< 
                                                      TList, 
                                                      mpl::inherit<FactoryUnit<mpl::_2, IdentifierType>, mpl::_1> 
                                                    >::type
{
public:
     typedef TList ProductList;   

     // Returns the factory of the desired type
     template <class T> 
     FactoryUnit<T>& GetFactoryUnitRef()
     {
	     return static_cast<FactoryUnit<T>&>(*this);
     }

     template <class T>
     bool Unregister(typename const FactoryUnit<T>::IDType& id)
     {
	     return GetFactoryUnitRef<T>().Unregister(id);
     }

     // Create several overloaded "Register" functions with upto MAX_ARGS arguments.
     #define MAX_ARGS 9
     #define BOOST_PP_LOCAL_MACRO(N)																     template <class T BOOST_PP_ENUM_TRAILING_PARAMS(N, class P)>										     typename FactoryUnit<T>::ProductPtr                                                                                     Register(typename const FactoryUnit<T>::IDType& id BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, P, p))	          {													                                                       FactoryUnit<T>& Unit = GetFactoryUnitRef<T>();	              					                    	     return Unit.Register(id, boost::bind(&T::Create, Unit.prototype BOOST_PP_ENUM_TRAILING_PARAMS(N, p)));        } 

     #define BOOST_PP_LOCAL_LIMITS (0, MAX_ARGS)
     #include BOOST_PP_LOCAL_ITERATE()	

};

} // namespace base
} // namespace drone



Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this