/* * Copyright (c) 2010-2013 Juli Mallett. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef COMMON_FACTORY_H #define COMMON_FACTORY_H #include #include template class Factory { public: Factory(void) { } virtual ~Factory() { } virtual C *create(void) const = 0; }; template class ConstructorFactory : public Factory { public: ConstructorFactory(void) { } ~ConstructorFactory() { } B *create(void) const { return (new C()); } }; template class ConstructorArgFactory : public Factory { A a_; public: ConstructorArgFactory(A a) : a_(a) { } ~ConstructorArgFactory() { } B *create(void) const { return (new C(a_)); } }; template class SubclassFactory : public Factory { Factory *factory_; public: SubclassFactory(Factory *factory) : factory_(factory) { } ~SubclassFactory() { delete factory_; factory_ = NULL; } B *create(void) const { return (factory_->create()); } }; template struct factory { Factory *operator() (void) const { return (new ConstructorFactory); } template Factory *operator() (T arg) const { return (new ConstructorArgFactory(arg)); } }; template class FactoryMap { typedef std::map *> map_type; map_type map_; public: FactoryMap(void) : map_() { } ~FactoryMap() { typename map_type::iterator it; while ((it = map_.begin()) != map_.end()) { delete it->second; map_.erase(it); } } C *create(const K& key) const { typename map_type::const_iterator it; it = map_.find(key); if (it == map_.end()) return (NULL); return (it->second->create()); } void enter(const K& key, Factory *factory) { typename map_type::iterator it; it = map_.find(key); if (it != map_.end()) { delete it->second; map_.erase(it); } map_[key] = factory; } template void enter(const K& key, Factory *factory) { enter(key, new SubclassFactory(factory)); } std::set keys(void) const { typename map_type::const_iterator it; std::set key_set; for (it = map_.begin(); it != map_.end(); ++it) key_set.insert(it->first); return (key_set); } }; #endif /* !COMMON_FACTORY_H */