www.pudn.com > Loki.rar > Factory.h


//////////////////////////////////////////////////////////////////////////////// 
// The Loki Library 
// Copyright (c) 2001 by Andrei Alexandrescu 
// This code accompanies the book: 
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design  
//     Patterns Applied". Copyright (c) 2001. Addison-Wesley. 
// Permission to use, copy, modify, distribute and sell this software for any  
//     purpose is hereby granted 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. 
// The author or Addison-Welsey Longman make no representations about the  
//     suitability of this software for any purpose. It is provided "as is"  
//     without express or implied warranty. 
//////////////////////////////////////////////////////////////////////////////// 
 
// Last update: May 19, 2002 
 
#ifndef FACTORY_INC_ 
#define FACTORY_INC_ 
 
#include "LokiTypeInfo.h" 
#include "AssocVector.h" 
#include  
 
namespace Loki 
{ 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template DefaultFactoryError 
// Manages the "Unknown Type" error in an object factory 
//////////////////////////////////////////////////////////////////////////////// 
 
    template  
    struct DefaultFactoryError 
    { 
        struct Exception : public std::exception 
        { 
            const char* what() const throw() { return "Unknown Type"; } 
        }; 
         
        static AbstractProduct* OnUnknownType(IdentifierType) 
        { 
            throw Exception(); 
        } 
    }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template Factory 
// Implements a generic object factory 
//////////////////////////////////////////////////////////////////////////////// 
 
    template 
    < 
        class AbstractProduct,  
        typename IdentifierType, 
        typename ProductCreator = AbstractProduct* (*)(), 
        template 
            class FactoryErrorPolicy = DefaultFactoryError 
    > 
    class Factory  
        : public FactoryErrorPolicy 
    { 
    public: 
        bool Register(const IdentifierType& id, ProductCreator creator) 
        { 
            return associations_.insert( 
                IdToProductMap::value_type(id, creator)).second; 
        } 
         
        bool Unregister(const IdentifierType& id) 
        { 
            return associations_.erase(id) == 1; 
        } 
         
        AbstractProduct* CreateObject(const IdentifierType& id) 
        { 
            typename IdToProductMap::iterator i = associations_.find(id); 
            if (i != associations_.end()) 
            { 
                return (i->second)(); 
            } 
            return OnUnknownType(id); 
        } 
         
    private: 
        typedef AssocVector IdToProductMap; 
        IdToProductMap associations_; 
    }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template CloneFactory 
// Implements a generic cloning factory 
//////////////////////////////////////////////////////////////////////////////// 
 
    template 
    < 
        class AbstractProduct,  
        class ProductCreator =  
            AbstractProduct* (*)(const AbstractProduct*), 
        template 
            class FactoryErrorPolicy = DefaultFactoryError 
    > 
    class CloneFactory 
        : public FactoryErrorPolicy 
    { 
    public: 
        bool Register(const TypeInfo& ti, ProductCreator creator) 
        { 
            return associations_.insert( 
                IdToProductMap::value_type(ti, creator)).second; 
        } 
         
        bool Unregister(const TypeInfo& id) 
        { 
            return associations_.erase(id) == 1; 
        } 
         
        AbstractProduct* CreateObject(const AbstractProduct* model) 
        { 
            if (model == 0) return 0; 
             
            typename IdToProductMap::iterator i =  
                associations_.find(typeid(*model)); 
            if (i != associations_.end()) 
            { 
                return (i->second)(model); 
            } 
            return OnUnknownType(typeid(*model)); 
        } 
         
    private: 
        typedef AssocVector IdToProductMap; 
        IdToProductMap associations_; 
    }; 
} // namespace Loki 
 
//////////////////////////////////////////////////////////////////////////////// 
// Change log: 
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! 
// May  10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) 
//////////////////////////////////////////////////////////////////////////////// 
 
#endif // FACTORY_INC_