Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

s11n::fac::factory_mgr< InterfaceT, KeyType > Class Template Reference

The factory_mgr class is essentially a static classloader, capable of loading classes by using registered factories for a given set of keys (e.g. More...

#include <factory.hpp>

List of all members.

Public Types

typedef KeyType key_type
 A typedef for the KeyType used by this class.
typedef InterfaceT value_type
 A typedef for the InterfaceT used by this class.
typedef InterfaceT * result_type
 Same as (InterfaceT *).
typedef aliaser< key_typealiaser_type
 A type used to map classname aliases for this factory manager.
typedef result_type(* factory_function_type )()
 The type of factories used by this class: a function taking void and returning (value_type ).
typedef std::map< key_type,
factory_function_type
factory_map_type
 Internal container type used for mapping keys to factories.

Public Member Functions

 factory_mgr ()
virtual ~factory_mgr () throw ()
aliaser_typealiases ()
 Returns the container of classname aliases.
const aliaser_typealiases () const
 Const overload.
virtual result_type create (const key_type &_key)
 Tries to instantiate an instance of value_type using the given key.
result_type operator() (const key_type &key)
 Returns create(key).
virtual void destroy (result_type obj)
 Simply calls delete obj.
virtual void register_factory (const key_type &key, factory_function_type fp)
 Registers a factory using the given key.
factory_map_typefactory_map ()
 Returns the internal key-to-factory map.
const factory_map_typefactory_map () const
 Const overload.
virtual bool provides (const key_type &key) const
 Returns true if the given key is registered (alias expansions are considered).

Static Public Member Functions

static factory_mgrinstance ()
 Returns a shared reference to a factory.


Detailed Description

template<class InterfaceT, class KeyType = std::string>
class s11n::fac::factory_mgr< InterfaceT, KeyType >

The factory_mgr class is essentially a static classloader, capable of loading classes by using registered factories for a given set of keys (e.g.

, class names).

Classloaders, at least in my experience, need to be able to load all classes which derive from some given type. Without a common base class, one can't safely attempt to cast from an arbitrary pointer to the type we want to load. That's where the InterfaceT parameter comes in. All objects instantiated via this loader must inherit (be-a) from InterfaceT, or must literally be InterfaceT.

KeyType is a type which specifies the type of key used to look up classes, defaulting to std::string.

For this implementation, both InterfaceT and KeyType must be Default Constructable, and InterfaceT must be constructable on the heap (e.g., via new InterfaceT()).

InterfaceT must be a "plain type", without any pointer, reference or const qualifications.

Sample usage:

		   factory_mgr<MyInterface> & fac = factory_mgr<MyInterface>::instance();
		   fac.register_factory( "my_key", s11n::fac::create_hook<MyInterface,MyClass>::create );
		   MyInterface *foo = fac.create( "some_key" ); // == NULL
		   foo = fac.create( "my_key" ); // == a new MyClass object
		   

Note that all instances of factory_mgr share the same factories and aliases maps. This is a design decision which is intended to simplify usage of the type and ensure consistency of state across module boundaries. In effect, the default implementation is a Monostate type, which each instance sharing the same data.

Trivia: above i mentioned "casting", but this implementation requires no casting of any type, neither in the library nor in client code (unless the client explicitely needs to do so for their own purposes).

Definition at line 253 of file factory.hpp.


Member Typedef Documentation

template<class InterfaceT, class KeyType = std::string>
typedef aliaser<key_type> s11n::fac::factory_mgr< InterfaceT, KeyType >::aliaser_type
 

A type used to map classname aliases for this factory manager.

Definition at line 287 of file factory.hpp.

template<class InterfaceT, class KeyType = std::string>
typedef result_type( * s11n::fac::factory_mgr< InterfaceT, KeyType >::factory_function_type)()
 

The type of factories used by this class: a function taking void and returning (value_type ).

See factory_map().

todo: implement proper functor support.

Definition at line 295 of file factory.hpp.

template<class InterfaceT, class KeyType = std::string>
typedef std::map< key_type, factory_function_type > s11n::fac::factory_mgr< InterfaceT, KeyType >::factory_map_type
 

Internal container type used for mapping keys to factories.

Definition at line 301 of file factory.hpp.

template<class InterfaceT, class KeyType = std::string>
typedef KeyType s11n::fac::factory_mgr< InterfaceT, KeyType >::key_type
 

A typedef for the KeyType used by this class.

Definition at line 265 of file factory.hpp.

template<class InterfaceT, class KeyType = std::string>
typedef InterfaceT* s11n::fac::factory_mgr< InterfaceT, KeyType >::result_type
 

Same as (InterfaceT *).

Definition at line 276 of file factory.hpp.

template<class InterfaceT, class KeyType = std::string>
typedef InterfaceT s11n::fac::factory_mgr< InterfaceT, KeyType >::value_type
 

A typedef for the InterfaceT used by this class.

For conformance with the Adaptable Unary Functor model

Definition at line 272 of file factory.hpp.


Constructor & Destructor Documentation

template<class InterfaceT, class KeyType = std::string>
s11n::fac::factory_mgr< InterfaceT, KeyType >::factory_mgr  )  [inline]
 

Definition at line 279 of file factory.hpp.

template<class InterfaceT, class KeyType = std::string>
virtual s11n::fac::factory_mgr< InterfaceT, KeyType >::~factory_mgr  )  throw () [inline, virtual]
 

Definition at line 281 of file factory.hpp.


Member Function Documentation

template<class InterfaceT, class KeyType = std::string>
const aliaser_type& s11n::fac::factory_mgr< InterfaceT, KeyType >::aliases  )  const [inline]
 

Const overload.

Definition at line 319 of file factory.hpp.

References s11nlite::instance().

template<class InterfaceT, class KeyType = std::string>
aliaser_type& s11n::fac::factory_mgr< InterfaceT, KeyType >::aliases  )  [inline]
 

Returns the container of classname aliases.

In this implementation the aliases are shared amongst all instances of this type, because that aligns it with the shared factory map.

Definition at line 311 of file factory.hpp.

References s11nlite::instance().

template<class InterfaceT, class KeyType = std::string>
virtual result_type s11n::fac::factory_mgr< InterfaceT, KeyType >::create const key_type _key  )  [inline, virtual]
 

Tries to instantiate an instance of value_type using the given key.

Returns 0 if no object could be loaded for the given key.

Subtypes are free to implement, e.g., DLL lookups.

This implementation calls aliases().expand(_key) to expand any aliased class names. Subclasses/specializations "should" do the same, but are not strictly required to.

Definition at line 337 of file factory.hpp.

template<class InterfaceT, class KeyType = std::string>
virtual void s11n::fac::factory_mgr< InterfaceT, KeyType >::destroy result_type  obj  )  [inline, virtual]
 

Simply calls delete obj.

Subclasses are free to do custom accounting, garbage collection, or whatever, by overriding this.

Note that it is NOT practical to expect all clients to call this in order to destroy their objects, so the utility of this function is HIGHLY arguable.

Also be aware that the simple delete behaviour is not suitable if InterfaceT is a populated container of dumb pointers, or otherwise contains unowned pointers.

Subclasses are free to "suggest" a must-destroy() policy if they wish, but cannot expect anyone to actually follow that wish. In pedantic terms, however, one should destroy an object from the same code module and thread which created it, to avoid low-level problems involving crossing module/thread boundaries. That's what Sutter and Alexandrescu say, anyway, and i'm not one to argue with them.

Definition at line 383 of file factory.hpp.

template<class InterfaceT, class KeyType = std::string>
const factory_map_type& s11n::fac::factory_mgr< InterfaceT, KeyType >::factory_map  )  const [inline]
 

Const overload.

Definition at line 463 of file factory.hpp.

References s11nlite::instance().

template<class InterfaceT, class KeyType = std::string>
factory_map_type& s11n::fac::factory_mgr< InterfaceT, KeyType >::factory_map  )  [inline]
 

Returns the internal key-to-factory map.

It is safe for clients to modify this except in multi-threaded environments, and then all guarantees go out the window. That said, it should never be necessary for clients to use this.

The default implementation returns the same map for all instances of ThisType. The reasoning behind using static factory maps is essentially this: we can only have one definition of each type. We normally want factories to always return an instance constructed in the same way. If we allow multiple factories per type we might introduce hard-to-track inconsistencies in client code, where different factories than intended are accidentally used. OTOH, private factory maps would open up some interesting possibilities.

TODO (well, to consider): use a hook or Traits type to allow the user to replace this object with his own, so that he can control the scope of the map more fully. Overkill. YAGNI. Christian Prochnow's experience in the P::Classes tree suggests that that would be Bad, anyway, because clients linking from different sources can end up with different instances of the map. This has never been witnessed using phoenix<> to share instances, however.

Definition at line 457 of file factory.hpp.

References s11nlite::instance().

template<class InterfaceT, class KeyType = std::string>
static factory_mgr& s11n::fac::factory_mgr< InterfaceT, KeyType >::instance  )  [inline, static]
 

Returns a shared reference to a factory.

The s11n core always calls this function to get factory instances.

Definition at line 497 of file factory.hpp.

References s11nlite::instance().

template<class InterfaceT, class KeyType = std::string>
result_type s11n::fac::factory_mgr< InterfaceT, KeyType >::operator() const key_type key  )  [inline]
 

Returns create(key).

Definition at line 352 of file factory.hpp.

References s11n::fac::create().

template<class InterfaceT, class KeyType = std::string>
virtual bool s11n::fac::factory_mgr< InterfaceT, KeyType >::provides const key_type key  )  const [inline, virtual]
 

Returns true if the given key is registered (alias expansions are considered).

This is sometimes useful for checking whether a factory needs to be re-registered, which is sometimes necessary post-main(), when the internal map gets hosed before clients are done using it.

The constness is arguable: subclasses/specializations could arguably do pre-lookups for DLLs (or similar) here, and might need non-const behaviour. As a consolation, we have made create() non-const, so (provides()==false) can symantically mean "we need to do a DLL lookup".

Definition at line 486 of file factory.hpp.

template<class InterfaceT, class KeyType = std::string>
virtual void s11n::fac::factory_mgr< InterfaceT, KeyType >::register_factory const key_type key,
factory_function_type  fp
[inline, virtual]
 

Registers a factory using the given key.

Note that fp may not be declared as returning a type other than (value_type *), but the actual object it creates may be a polymorphic subclass of value_type. See the create_hook class for a factory which does this subtype-to-base conversion.

For ABSTRACT interface types, you "should" register a no-op factory which simply returns 0. The difference between registering a no-op factory and registering NO factory is that when create() is called, if NO factory is found, this type is free to implement extra logic like DLL lookups to try to find the type (which is futile for an abstract type). However, if it has a registered factory, it will not do this (it doesn't care if the factory returns 0 or not).

Subclasses are free to add behaviour, like instrumentation, but should not forget to actually carry through on the registration part (e.g., by calling this implementation).

Definition at line 417 of file factory.hpp.


The documentation for this class was generated from the following file:
Generated on Sat Dec 10 13:42:03 2005 for libs11n-1.2.1 by  doxygen 1.4.4