1//
2// DynamicFactory.h
3//
4// Library: Foundation
5// Package: Core
6// Module: DynamicFactory
7//
8// Definition of the DynamicFactory class.
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_DynamicFactory_INCLUDED
18#define Foundation_DynamicFactory_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/Instantiator.h"
23#include "Poco/Exception.h"
24#include "Poco/Mutex.h"
25#include <map>
26#include <memory>
27
28
29namespace Poco {
30
31
32template <class Base>
33class DynamicFactory
34 /// A factory that creates objects by class name.
35{
36public:
37 typedef AbstractInstantiator<Base> AbstractFactory;
38
39 DynamicFactory()
40 /// Creates the DynamicFactory.
41 {
42 }
43
44 ~DynamicFactory()
45 /// Destroys the DynamicFactory and deletes the instantiators for
46 /// all registered classes.
47 {
48 for (typename FactoryMap::iterator it = _map.begin(); it != _map.end(); ++it)
49 {
50 delete it->second;
51 }
52 }
53
54 Base* createInstance(const std::string& className) const
55 /// Creates a new instance of the class with the given name.
56 /// The class must have been registered with registerClass.
57 /// If the class name is unknown, a NotFoundException is thrown.
58 {
59 FastMutex::ScopedLock lock(_mutex);
60
61 typename FactoryMap::const_iterator it = _map.find(className);
62 if (it != _map.end())
63 return it->second->createInstance();
64 else
65 throw NotFoundException(className);
66 }
67
68 template <class C>
69 void registerClass(const std::string& className)
70 /// Registers the instantiator for the given class with the DynamicFactory.
71 /// The DynamicFactory takes ownership of the instantiator and deletes
72 /// it when it's no longer used.
73 /// If the class has already been registered, an ExistsException is thrown
74 /// and the instantiator is deleted.
75 {
76 registerClass(className, new Instantiator<C, Base>);
77 }
78
79 void registerClass(const std::string& className, AbstractFactory* pAbstractFactory)
80 /// Registers the instantiator for the given class with the DynamicFactory.
81 /// The DynamicFactory takes ownership of the instantiator and deletes
82 /// it when it's no longer used.
83 /// If the class has already been registered, an ExistsException is thrown
84 /// and the instantiator is deleted.
85 {
86 poco_check_ptr (pAbstractFactory);
87
88 FastMutex::ScopedLock lock(_mutex);
89
90 std::unique_ptr<AbstractFactory> ptr(pAbstractFactory);
91 typename FactoryMap::iterator it = _map.find(className);
92 if (it == _map.end())
93 _map[className] = ptr.release();
94 else
95 throw ExistsException(className);
96 }
97
98 void unregisterClass(const std::string& className)
99 /// Unregisters the given class and deletes the instantiator
100 /// for the class.
101 /// Throws a NotFoundException if the class has not been registered.
102 {
103 FastMutex::ScopedLock lock(_mutex);
104
105 typename FactoryMap::iterator it = _map.find(className);
106 if (it != _map.end())
107 {
108 delete it->second;
109 _map.erase(it);
110 }
111 else throw NotFoundException(className);
112 }
113
114 bool isClass(const std::string& className) const
115 /// Returns true iff the given class has been registered.
116 {
117 FastMutex::ScopedLock lock(_mutex);
118
119 return _map.find(className) != _map.end();
120 }
121
122private:
123 DynamicFactory(const DynamicFactory&);
124 DynamicFactory& operator = (const DynamicFactory&);
125
126 typedef std::map<std::string, AbstractFactory*> FactoryMap;
127
128 FactoryMap _map;
129 mutable FastMutex _mutex;
130};
131
132
133} // namespace Poco
134
135
136#endif // Foundation_DynamicFactory_INCLUDED
137