Suggestions for Loki::Factory class.

2008-02-28
2013-04-08
  • Alexey Kharlov

    Alexey Kharlov - 2008-02-28

    At first I'd show code of Factory that I use in my projects, based on first Loki library design:

         template <class IdentifierType, class ProductType>
         class DefaultFactoryError
         {
         public:
             static ProductType OnUnknownType(const IdentifierType &id) { return NULL; } // or throw exception
         };

         // factory class
         template
         <
             class AbstractProduct,
             class IdentifierType,
             class ProductCreator = AbstractProduct (*)(),
             class FactoryErrorPolicy = DefaultFactoryError<IdentifierType, AbstractProduct>,
             class MapCompareTraits = std::less<IdentifierType>
         >
         class Factory
         {
         public:
             bool Register(const IdentifierType &id, ProductCreator creator)
             {
                 return associations.insert(AssocMap::value_type(id, creator)).second;
             }

             bool Unregister(const IdentifierType &id)
             {
                 return associations.erase(id) == 1;
             }

             AbstractProduct CreateObject(const IdentifierType &id)
             {
                 typename AssocMap::const_iterator i = associations.find(id);
                 if (i != associations.end())
                     return (i->second)();
                 return FactoryErrorPolicy::OnUnknownType(id);
             }
        private:
             typedef std::map<IdentifierType, ProductCreator, MapCompareTraits> AssocMap;
             AssocMap associations;
        };

    New view of Loki impressed me, it's very convinient, but lets have a look on little improvements in comparison with base design.

    1) Look at CreateObject()-function's return type:
        AbstractProduct CreateObject(const IdentifierType &id)

    The suggeston is to more generalize type of AbstractProduct (removed asterisk).
    What you will do when you need return some smart pointer as AbstractProduct
    (for example, boost::shared_ptr or Loki::SmartPtr)?

    There is lose of Object creation context in ProductCreator...
    Only ProductCreator knows how to free memory when object not needed more.

    Design imperfection of Loki::Factory class (in my opinion) -
    returning pointers from CreateObject() functions.
    The only thing we need to correct this is to remove pointer's "stars".

    Look at some ProductCreator in this case (example):

    typedef boost::shared_ptr<BaseClass> BaseClassPtr;
    BaseClassPtr Create_Derived()
    {
        void *some = malloc(sizeof(Derived));
        new(some) Derived();
        return BaseClassPtr(some, &free);
    }

    The only necessary changing in current supported code (that returning pointer to AbstractProduct) -
    is tuning Factory typedefs with introduce "star":

    typedef Loki::Factory<SupportedBase*, IdentifierType> FactoryType;

    2) And the second suggestion: make last template parameter for compare keys (IdentifierType)
    in associative map (or associative vector in Loki-lib, because it is supported feature).

    Then we can use "C" strings (const char *, null-terminated strings) as IdentifierType with functor:

    class CharCompareTraits : public std::binary_function<const char*, const char*, bool>
    {
    public:
        bool operator()(const char *left, const char *right) const
        {
             return strcmp(left, right) < 0;
        }
    };

     
    • Bit Bucket

      Bit Bucket - 2009-04-08

      I concur with the first part of this post. I'd really like to be able to wrap my factory products up inside some kind of smart pointer before returning them. Does anyone have a clean alternate solution that they have been using?

      Thanks.

       

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks