I am designing a library that creates a family of classes and manages it. I need to design config class that is used to instantiate instances from the classes. This config class is just config information.
what is the best way to design the config classes? Should the config class contain the superset of information required to create objects of any class in the family? Or, should there be a hierarchy of classes mirroring the hierarchy of actual classes.
For a concrete example. Lets say I have a library called animalManager which creates various animals based on user config and manages:
class animal { // Animal base class
public:
animal(bool isHerbivore, bool isMammal, bool isNocturnal) :
mIsHerbivore(isHerbivore), mIsMammal(isMammal), mIsNocturnal(isNocturnal) { }
virtual ~animal() { }
// methods that do stuffs..
private:
bool mIsHerbivore;
bool mIsMammal;
bool mIsNocturnal;
};
class snake : public animal { // Snake animal
public:
snake(bool isHerbivore, bool isMammal, bool isNocturnal, bool haveHood) :
animal(isHerbivore, isMammal, isNocturnal), mHaveHood(haveHood) { }
virtual ~snake() {}
private:
bool mHaveHood;
};
class fish : public animal {
public:
fish(bool isHerbivore, bool isMammal, bool isNocturnal, int numFins) :
animal(isHerbivore, isMammal, isNocturnal), mNumFins(numFins) {
}
virtual ~fish() {}
private:
int mNumFins;
};
// Cat, parrot, elephant, so on
class animalConfig { // User settings to create animals
// What is the best way to design this class (/hierarchy) ?
};
class animalManager
{
public:
animalManager() {}
~animalManager() {}
animal* createAnimal(animalConfig *settings) {
// Create and return animal
}
// So on
};
In the above example, snake and fish needs additional config on top of animal config. How to represent these config?
I suggest to have meta_class instances that the factory function uses in config parsing and generating the real animal classes and a animalConfig that is little more than a stream. You have one meta_class object for each real class.
class base_animals;
struct meta_base
{
static std::vector< meta_base* > meta_base_list;
meta_base(...):fn_(...), recognition_data_(...) { meta_base_list.push_back( this ); }
std::unique_ptr< base_animals > fn_( animalConfig * );
std::string recognition_data_;
};
class rabbit: public base_animal
{
static meta_base mb;
static std::unique_ptr< base_animals > make_bunny( animalConfig * );
...
};
// In source file
meta_base rabbit::mb( &rabbit::make_bunny, "rabbit" );
Then you have a list of these meta objects that animal* createAnimal(animalConfig *settings) can use to instantiate arbitrary animal types.
for( auto meta* : meta_base::meta_base_list )
{
if( settings->section_label() == meta->recognition_data_ )
{
return *(meta->fn_)( settings );
}
// Handle case where no meta class found
}
The input data for this could be a stream containing text like:
section rabbit
length X
weight Y
end
The animalConfig searches for the text "section" and gets the label "rabbit" (which it stores and returns from section_label()), the rabbit::make_bunny method is then responsible for parsing the values specific for the rabbit. I don't think trying to create an animalConfig class with a superset of all specific data is easier.
First of all, I beg your pardon if this question has been already answered, but I simply cannot be sure of my choice.
I am working on a C++ game engine and I want it to be according to the modern standards. I wrote it in OOP manner and I have a main class called ENGINE. Inside it, there are a couple of class instances that represent specific subsystems: WINDOW, D3D11_RENDERER, etc. I also have a logging system (LOGGER) which must be available to all subsystems.
Now, this global access to the logger poses me a problem. I am uncertain whether I should declare it as static, outside the ENGINE class and have a function that returns a reference to it or instance it inside ENGINEand make all subsystems point to it.
To give you a better idea of what I am talking about, I posted simplified versions of these scenarios (take into account that I removed a lot of meaningless functions).
First solution:
class LOGGER {...};
LOGGER* GetLogger()
{
static LOGGER Logger;
return &Logger;
}
// Just one example.
class WINDOW
{
void Function()
{
GetLogger()->Write();
}
};
class ENGINE
{
private:
WINDOW Window;
}
Note that Irrlicht engine does it like this:
class Printer
{
public:
static void Write();
static LOGGER* Logger;
};
And it can be globally accessed like this:
os::Printer::Write();
Second solution:
class LOGGER() {...};
// Same example.
class WINDOW
{
public:
void Initialize(LOGGER* pLogger)
{
Logger = pLogger;
}
void Function()
{
Logger->Write();
}
private:
LOGGER* Logger;
};
class ENGINE
{
public:
void Initialize()
{
Window.Initialize(&Logger);
}
private:
WINDOW Window;
LOGGER Logger;
}
I do not know which is the best solution and I would be glad if you could point me to the right one. Thank you in advance.
I think this diagram represents better what you need:
Your components should be log-agnostic, as their function don't depend on logging capabilities. This function should be delegated to the engine.
The engine itself can contain a Logger component, which handles the de facto logging.
So let's see some basic code:
class Engine {
private:
Logger& mLogger;
EngineComponent mComponents[10];
public:
Engine(Logger& logger):
mLogger(logger) {
}
void addComponent(EngineComponent& c, int pos) {
mComponents[pos] = c;
c.setEngine(this);
}
void log(const std::string& message) {
mLogger.write(message);
}
}
class EngineComponent {
private:
Engine* mEngine;
protected:
EngineComponent() {}
public:
void setEngine(Engine* engine) {
mEngine = engine;
}
void log(const std::string& message) {
if (mEngine != NULL) {
mEngine->log(message);
}
}
}
class Window : public EngineComponent {
// add implementation
}
class D3d11Renderer : public EngineComponent {
// add implementation
}
class Logger {
protected:
Logger() {}
}
class FileLogger : public Logger {
// add implementation
}
Hope it helps.
I have a task to implement fluent interface for a class, which consist of other classes. Let's say we have a class:
class Pizza {
int price, size;
}
class Foo {
string name;
Pizza p1, p2;
}
I would like to use code like:
Foo f = FooBuilder().setName("foo")
.settingP1().setPrice(5).setSize(1)
.settingP2().setPrice(2)
.build();
but I also would like to forbid code like:
Foo f = FooBuilder().setName("foo").setPrice(5);
I thought about a class inherited from FooBuilder which is returned after calling .settingP1() but I am not sure how to do it. Notice that I don't want to write .build() when I ended specifying Pizza object.
EDIT: Maybe I should've mentioned that when I wrote .settingP2().setPrice(2) without writing .setSize(sth) I meant that size will just have default value. I want to be able to "jump" to the next object regardless of specifying all attributes or not
EDIT2: I know how to implement the Builder pattern and fluent interface for classes which have fields of basic types. The problem is I want the code
Foo f = FooBuilder().setName("foo").setPrice(5);
to not compile. Maybe it's impossible to write such a builder.
If you don't mind, I'll write solution for your problem in Java, hopefully you'll be able to apply it in C++ without anyu problem.
You have 2 options.
More verbose DSL (I prefer not to call your problem Builder any more, but either Fluent API, or DSL - Domain Specific Language, as it defines grammar rules for it) with simpler implementation
or simpler DSL (exactly what you wrote) with a small trick in the implenmentation.
For optiona #1 your usage would look like this:
new FooBuilder().setName("Foo")
.settingP1().setPrice(5).setSize(1).end()
.settingP2().setPrice(2).end()
.build();
Notice additional methods end(). Corresponding code in Java would look like this:
public class FooBuilder {
public FooBuilder setName(String name) {
// Store the name
return this;
}
public PizzaBuilder settingP1() {
return new PizzaBuilder(pizza1, this);
}
public PizzaBuilder settingP2() {
return new PizzaBuilder(pizza2, this);
}
public Foo build() {
// return Foo build using stored information
}
}
public class PizzaBuilder {
private final Pizza pizza;
private final FooBuilder foo;
// Constructor
public PizzaBuilder(Pizza pizza, FooBuilder foo) {
this.pizza = pizza;
this.foo = foo;
}
public PizzaBuilder setPrice(int price) {
// update pizza price
return this;
}
public PizzaBuilder setSize(int size) {
// update pizza size
return this;
}
// With this method you return to parent, and you can set second pizza.
public FooBuilder end() {
return foo;
}
}
Now for option #2 I'd do another generalization to your problem to allow defining any number of pizzas. I'd also omit set prefix, it's not usual for DSL:
new FooBuilder().name("Foo")
.addPizzaWith().price(5).size(1)
.addPizzaWith().price(2)
.build();
Now the implementation will look like:
public class FooBuilder {
public FooBuilder(String name) {
// Store name
return this;
}
public PizzaBuilder addPizzaWith() {
Pizza pizza = createAndStorePizza(); // Some private method to do what is says
return new PizzaBuilder(pizza, this);
}
public Foo build() {
// Build and return the Foo using stored data
}
}
public class PizzaBuilder {
private final Pizza pizza;
private final FooBuilder foo;
public PizzaBuilder(Pizza pizza, FooBuilder foo) {
this.pizza = pizza;
this.foo = foo;
}
public PizzaBuilder price(int value) {
// Store price value
return this;
}
public PizzaBuilder size(int value) {
// Store size value
return this;
}
// This method does the trick - it terminates first pizza specification,
// and delegates entering second (or any other) pizza specification to
// the parent FooBuilder.
public PizzaBuilder addPizzaWith() {
return foo.addPizzaWith();
}
// Another similar trick with allowing to call build directly on Pizza
// specification
public Foo build() {
return foo.build();
}
}
There is one noticeable attribute - circular dependency. FooBuilder must know PizzaBuilder, and PizzaBuilder must know FooBuilder. In Java it's not an issue.
If I remember correctly, you can solve it in C++ too by declaring first just the
type using forward declaration or so.
It would also be typically beneficial for the second example in Java to introduce an interface with methods build() and addPizzaWith(), which both classes implement. So you can e.g. add pizzas in cycle without any issue.
Dmitri Nesteruk has written a "facet builder" example that is pretty much what you are trying to achieve.
The basic structure would be something like (almost pseudo code):
class FooBuilderBase {
protected:
Foo& foo; // reference to derived builders
FooBuilderBase(Foo& f) : foo(f) {}
public:
PizzaBuilder settingP1() { return PizzaBuilder(foo, foo.p1); }
PizzaBuilder settingP2() { return PizzaBuilder(foo, foo.p2); }
};
class FooBuilder : public FooBuilderBase {
Foo foo_; // real instance
public:
FooBuilder() : FooBuilderBase(foo_) {}
FooBuilder& setName(string n) { foo.name = n; return *this; }
};
class PizzaBuilder : public FooBuilderBase {
Pizza& pizza;
public:
PizzaBuilder(Foo& f, Pizza& p) : FooBuilderBase(f), pizza(p) {}
PizzaBuilder& setPrice(int p) { pizza.price = p; return *this; }
};
You can add a FooPizzaBuilder class as derrivate of FooBuilder.
By doing this you seperate the building of your Pizza classes and the building of the actual Foo class.
Consider the following code:
enum class PizzaNum {
ONE, TWO
}
class FooPizzaBuilder;
class FooBuilder {
public:
FooBuilder();
FooBuilder setName();
FooPizzaBuilder settingP1();
FooPizzaBuilder settingP2();
Foo build();
protected:
void _setPrize(PizzaNum); //Don't expose _setPrice() to user
void _setSize(PizzaNum); //Don't expose _setSize() to user
}
class FooPizzaBuilder : public FooBuilder {
public:
FooPizzaBuilder(PizzaNum pizzaNum)
FooPizzaBuilder setPrice(); //Call _setPrice()
FooPizzaBuilder setSize(); //Call _setSize()
}
This requires you to call settingP1() before making a call to setPrice();
An easy way to make the code type safe is to add an enum class to FooBuilder.
class FooBuilder {
public:
enum class PizzaNum {
ONE,
TWO
}
}
and...
FooBuilder& FooBuilder::setPrice(const PizzaNum pizzaNum, const int price) {
switch (pizzaNum) {
case PizzaNum::ONE:
p1.setPrice(price);
break;
case PizzaNum::TWO:
p2.setPrice(price);
break;
}
return this;
}
Then, you need to pass the enum to the method otherwise it results in a compile time error (e.g. .setPrice(FooBuilder::PizzaNum::ONE, 5).
Note, this is non-variadic.
I am creating a library in C++ with the intent of utilizing it in future applications (games). I decided on using an Entity-Property design where a base entity can be extended by attaching various properties to it. Properties are all derivatives of a base GameProperty class which allows them to be stored in a single vector of polymorphic pointers, which is a member of the GameEntity class. I have an EntityManager class which creates specialized entities by attaching the correct set of properties to them, in accordance with an EntityTemplate that can be loaded from file.
Here is the problem: I want it to be easy to create and add new properties to suit the needs of a given project. But each new property cannot simply extend GameProperty, it needs to as seemlessly as possible be integratable into the EntityManager. The EntityManager expects strings like "GraphicsProperty", "InputProperty", etc and then selects which property to attach to newly created entities based on that. How can I structure the Property and EntityManager classes in such a way that typespecific code does not need to be added to EntityManager for each new Property I write?
Consider the example below:
class GameProperty
{
virtual void Update() = 0;
};
class GraphicsProperty : public GameProperty
{
void Update();
};
class InputProperty : public GameProperty
{
void Update();
};
class GameEntity
{
public:
void AttachProperty(shared_ptr<GameProperty> newProperty)
{
properties.push_back(newProperty);
};
vector<shared_ptr<GameProperty>> properties;
};
class EntityTemplate
{
public:
vector<string> properties;
};
class EntityManager
{
public:
std::shared_ptr<GameEntity>
EntityManager::CreateEntityFromTemplate(shared_ptr<EntityTemplate> entityTemplate)
{
std::shared_ptr<GameEntity> newEntity = make_shared<GameEntity>();
for each(string propertyName in entityTemplate->properties)
{
if(propertyName == "GraphicsProperty")
{
shared_ptr<GraphicsProperty> gProperty = make_shared<Graphics::GraphicsProperty>();
newEntity->AttachProperty(gProperty);
}
else if(propertyName == "InputProperty")
{
shared_ptr<Input::InputProperty> iProperty = make_shared<Input::InputProperty>();
newEntity->AttachProperty(iProperty);
}
}
};
};
Not seen above is the EntityLoader that creates EntityTemplate objects from an XML file.
You can register all the properties to construct an array of property factories and use the factories in your entity manager to create them, e.g.
class GamePropertyFactoryBase
{
public:
virtual GameProperty *Create() const=0;
};
template<class T>
class GamePropertyFactory: public GamePropertyFactoryBase
{
public:
virtual GameProperty *Create() const {return new T;}
};
typedef std::pair<const GamePropertyFactoryBase*, const char*> FactoryEntry_t;
std::vector<FactoryEntry_t> s_propertyFactories;
template<class T>
void RegisterProperty(const char *name_)
{
static const GamePropertyFactory<T> s_factory;
s_propertyFactories.push_back(FactoryEntry_t(&s_factory, name_));
}
void RegisterEntities()
{
// register all properties here
RegisterProperty<GraphicsProperty>("GraphicsProperty");
};
Then in the EntityManager search the name from the array and call:
GameProperty *prop=it->first->Create();
In my application, there are 10-20 classes that are instantiated once[*]. Here's an example:
class SomeOtherManager;
class SomeManagerClass {
public:
SomeManagerClass(SomeOtherManager*);
virtual void someMethod1();
virtual void someMethod2();
};
Instances of the classes are contained in one object:
class TheManager {
public:
virtual SomeManagerClass* someManagerClass() const;
virtual SomeOtherManager* someOtherManager() const;
/** More objects... up to 10-20 */
};
Currently TheManager uses the new operator in order to create objects.
My intention is to be able to replace, using plugins, the SomeManagerClass (or any other class) implementation with another one. In order to replace the implementation, 2 steps are needed:
Define a class DerivedSomeManagerClass, which inherits SomeManagerClass [plugin]
Create the new class (DerivedSomeManagerClass) instead of the default (SomeManagerClass) [application]
I guess I need some kind of object factory, but it should be fairly simple since there's always only one type to create (the default implementation or the user implementation).
Any idea about how to design a simple factory like I just described? Consider the fact that there might be more classes in the future, so it should be easy to extend.
[*] I don't care if it happens more than once.
Edit: Please note that there are more than two objects that are contained in TheManager.
Assuming a class (plugin1) which inherits from SomeManagerClass, you need a class hierarchy to build your types:
class factory
{
public:
virtual SomeManagerClass* create() = 0;
};
class plugin1_factory : public factory
{
public:
SomeManagerClass* create() { return new plugin1(); }
};
Then you can assign those factories to a std::map, where they are bound to strings
std::map<string, factory*> factory_map;
...
factory_map["plugin1"] = new plugin1_factory();
Finally your TheManager just needs to know the name of the plugin (as string) and can return an object of type SomeManagerClass with just one line of code:
SomeManagerClass* obj = factory_map[plugin_name]->create();
EDIT: If you don't like to have one plugin factory class for each plugin, you could modify the previous pattern with this:
template <class plugin_type>
class plugin_factory : public factory
{
public:
SomeManagerClass* create() { return new plugin_type(); }
};
factory_map["plugin1"] = new plugin_factory<plugin1>();
I think this is a much better solution. Moreover the 'plugin_factory' class could add itself to the 'factory_map' if you pass costructor the string.
I think there are two separate problems here.
One problem is: how does TheManager name the class that it has to create? It must keep some kind of pointer to "a way to create the class". Possible solutions are:
keeping a separate pointer for each kind of class, with a way to set it, but you already said that you don't like this as it violates the DRY principle
keeping some sort of table where the key is an enum or a string; in this case the setter is a single function with parameters (of course if the key is an enum you can use a vector instead of a map)
The other problem is: what is this "way to create a class"? Unfortunately we can't store pointers to constructors directly, but we can:
create, as others have pointed out, a factory for each class
just add a static "create" function for each class; if they keep a consistent signature, you can just use their pointers to functions
Templates can help in avoiding unnecessary code duplication in both cases.
I have answered in another SO question about C++ factories. Please see there if a flexible factory is of interest. I try to describe an old way from ET++ to use macros which has worked great for me.
ET++ was a project to port old MacApp to C++ and X11. In the effort of it Eric Gamma etc started to think about Design Patterns
I'd create a "base" factory that has virtual methods for creation of all the basic managers, and let the "meta manager" (TheManager in your question) take a pointer to the base factory as a constructor parameter.
I'm assuming that the "factory" can customize the instances of CXYZWManager by deriving from them, but alternatively the constructor of CXYZWManager could take different arguments in the "custom" factory.
A lengthy code example that outputs "CSomeManager" and "CDerivedFromSomeManager":
#include <iostream>
//--------------------------------------------------------------------------------
class CSomeManager
{
public:
virtual const char * ShoutOut() { return "CSomeManager";}
};
//--------------------------------------------------------------------------------
class COtherManager
{
};
//--------------------------------------------------------------------------------
class TheManagerFactory
{
public:
// Non-static, non-const to allow polymorphism-abuse
virtual CSomeManager *CreateSomeManager() { return new CSomeManager(); }
virtual COtherManager *CreateOtherManager() { return new COtherManager(); }
};
//--------------------------------------------------------------------------------
class CDerivedFromSomeManager : public CSomeManager
{
public:
virtual const char * ShoutOut() { return "CDerivedFromSomeManager";}
};
//--------------------------------------------------------------------------------
class TheCustomManagerFactory : public TheManagerFactory
{
public:
virtual CDerivedFromSomeManager *CreateSomeManager() { return new CDerivedFromSomeManager(); }
};
//--------------------------------------------------------------------------------
class CMetaManager
{
public:
CMetaManager(TheManagerFactory *ip_factory)
: mp_some_manager(ip_factory->CreateSomeManager()),
mp_other_manager(ip_factory->CreateOtherManager())
{}
CSomeManager *GetSomeManager() { return mp_some_manager; }
COtherManager *GetOtherManager() { return mp_other_manager; }
private:
CSomeManager *mp_some_manager;
COtherManager *mp_other_manager;
};
//--------------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
TheManagerFactory standard_factory;
TheCustomManagerFactory custom_factory;
CMetaManager meta_manager_1(&standard_factory);
CMetaManager meta_manager_2(&custom_factory);
std::cout << meta_manager_1.GetSomeManager()->ShoutOut() << "\n";
std::cout << meta_manager_2.GetSomeManager()->ShoutOut() << "\n";
return 0;
}
Here's the solution I thought of, it's not the best one but maybe it will help to think of better solutions:
For each class there would be a creator class:
class SomeManagerClassCreator {
public:
virtual SomeManagerClass* create(SomeOtherManager* someOtherManager) {
return new SomeManagerClass(someOtherManager);
}
};
Then, the creators will be gathered in one class:
class SomeManagerClassCreator;
class SomeOtherManagerCreator;
class TheCreator {
public:
void setSomeManagerClassCreator(SomeManagerClassCreator*);
SomeManagerClassCreator* someManagerClassCreator() const;
void setSomeOtherManagerCreator(SomeOtherManagerCreator*);
SomeOtherManagerCreator* someOtherManagerCreator() const;
private:
SomeManagerClassCreator* m_someManagerClassCreator;
SomeOtherManagerCreator* m_someOtherManagerCreator;
};
And TheManager will be created with TheCreator for internal creation:
class TheManager {
public:
TheManager(TheCreator*);
/* Rest of code from above */
};
The problem with this solution is that it violates DRY - for each class creator I would have to write setter/getter in TheCreator.
This seems like it would be a lot simpler with function templating as opposed to an Abstract Factory pattern
class ManagerFactory
{
public:
template <typename T> static BaseManager * getManager() { return new T();}
};
BaseManager * manager1 = ManagerFactory::template getManager<DerivedManager1>();
If you want to get them via a string, you can create a standard map from strings to function pointers. Here is an implementation that works:
#include <map>
#include <string>
class BaseManager
{
public:
virtual void doSomething() = 0;
};
class DerivedManager1 : public BaseManager
{
public:
virtual void doSomething() {};
};
class DerivedManager2 : public BaseManager
{
public:
virtual void doSomething() {};
};
class ManagerFactory
{
public:
typedef BaseManager * (*GetFunction)();
typedef std::map<std::wstring, GetFunction> ManagerFunctionMap;
private:
static ManagerFunctionMap _managers;
public:
template <typename T> static BaseManager * getManager() { return new T();}
template <typename T> static void registerManager(const std::wstring& name)
{
_managers[name] = ManagerFactory::template getManager<T>;
}
static BaseManager * getManagerByName(const std::wstring& name)
{
if(_managers.count(name))
{
return _managers[name]();
}
return NULL;
}
};
// the static map needs to be initialized outside the class
ManagerFactory::ManagerFunctionMap ManagerFactory::_managers;
int _tmain(int argc, _TCHAR* argv[])
{
// you can get with the templated function
BaseManager * manager1 = ManagerFactory::template getManager<DerivedManager1>();
manager1->doSomething();
// or by registering with a string
ManagerFactory::template registerManager<DerivedManager1>(L"Derived1");
ManagerFactory::template registerManager<DerivedManager2>(L"Derived2");
// and getting them
BaseManager * manager2 = ManagerFactory::getManagerByName(L"Derived2");
manager2->doSomething();
BaseManager * manager3 = ManagerFactory::getManagerByName(L"Derived1");
manager3->doSomething();
return 0;
}
EDIT: In reading the other answers I realized that this is very similar to Dave Van den Eynde's FactorySystem solution, but I'm using a function template pointer instead of instantiating templated factory classes. I think my solution is a little more lightweight. Due to static functions, the only object that gets instantiated is the map itself. If you need the factory to perform other functions (DestroyManager, etc.), I think his solution is more extensible.
You could implement an object factory with static methods that return an instance of a Manager-Class. In the factory you could create a method for the default type of manager and a method for any type of manager which you give an argument representing the type of the Manager-Class (say with an enum). This last method should return an Interface rather than a Class.
Edit: I'll try to give some code, but mind that my C++ times are quite a while back and I'm doing only Java and some scripting for the time being.
class Manager { // aka Interface
public: virtual void someMethod() = 0;
};
class Manager1 : public Manager {
void someMethod() { return null; }
};
class Manager2 : public Manager {
void someMethod() { return null; }
};
enum ManagerTypes {
Manager1, Manager2
};
class ManagerFactory {
public static Manager* createManager(ManagerTypes type) {
Manager* result = null;
switch (type) {
case Manager1:
result = new Manager1();
break;
case Manager2:
result = new Manager2();
break;
default:
// Do whatever error logging you want
break;
}
return result;
}
};
Now you should be able to call the Factory via (if you've been able to make the code sample work):
Manager* manager = ManagerFactory.createManager(ManagerTypes.Manager1);
I would use templates like this as I can't see the point of factories classes:
class SomeOtherManager;
class SomeManagerClass {
public:
SomeManagerClass(SomeOtherManager*);
virtual void someMethod1();
virtual void someMethod2();
};
class TheBaseManager {
public:
//
};
template <class ManagerClassOne, class ManagerClassOther>
class SpecialManager : public TheBaseManager {
public:
virtual ManagerClassOne* someManagerClass() const;
virtual ManagerClassOther* someOtherManager() const;
};
TheBaseManager* ourManager = new SpecialManager<SomeManagerClass,SomeOtherManager>;
You should take a look at the tutorial at
http://downloads.sourceforge.net/papafactory/PapaFactory20080622.pdf?use_mirror=fastbull
It contains a great tutorial on implementing an Abstract factory in C++ and the source code that comes with it is also very robust
Chris
Mh I don't understand a hundred percent, and I am not really into factory stuff from books and articles.
If all your managers share a similar interface you could derive from a base class, and use this base class in your program.
Depending on where the decision which class will be created will be made, you have to use an identifier for creation (as stated above) or handle the decision which manager to instantiate internally.
Another way would be to implement it "policy" like by using templates. So that You ManagerClass::create() returns a specific SomeOtherManagerWhatever instance. This would lay the decision which manager to make in the code which uses your Manager - Maye this is not intended.
Or that way:
template<class MemoryManagment>
class MyAwesomeClass
{
MemoryManagment m_memoryManager;
};
(or something like that)
With this construct you can easily use other managers by only changing the instantiation of MyAwesomeClass.
Also A class for this purpose might be a little over the top. In your case a factory function would do I guess. Well it's more a question of personal preference.
If you plan on supporting plugins that are dynamically linked, your program will need to provide a stable ABI (Application Binary Interface), that means that you cannot use C++ as your main interface as C++ has no standard ABI.
If you want plugins to implement an interface you define yourself, you will have to provide the header file of the interface to plugin programmer and standardize on a very simple C interface in order to create and delete the object.
You cannot provide a dynamic library that will allow you to "new" the plugin class as-is. That is why you need to standardize on a C interface in order to create the object. Using the C++ object is then possible as long as none of your arguments use possibly incompatible types, like STL containers. You will not be able to use a vector returned by another library, because you cannot ensure that their STL implementation is the same as yours.
Manager.h
class Manager
{
public:
virtual void doSomething() = 0;
virtual int doSomethingElse() = 0;
}
extern "C" {
Manager* newManager();
void deleteManager(Manager*);
}
PluginManager.h
#include "Manager.h"
class PluginManager : public Manager
{
public:
PluginManager();
virtual ~PluginManager();
public:
virtual void doSomething();
virtual int doSomethingElse();
}
PluginManager.cpp
#include "PluginManager.h"
Manager* newManager()
{
return new PluginManager();
}
void deleteManager(Manager* pManager)
{
delete pManager;
}
PluginManager::PluginManager()
{
// ...
}
PluginManager::~PluginManager()
{
// ...
}
void PluginManager::doSomething()
{
// ...
}
int PluginManager::doSomethingElse()
{
// ...
}
You didnt talk about TheManager. It looks like you want that to control which class is being used? or maybe you trying to chain them together?
It sounds like you need a abstract base class and a pointer to the currently used class. If you wish to chain you can do it in both abstract class and themanager class. If abstract class, add a member to the next class in chain, if themanager then sort it in order you which to use in a list. You'll need a way to add classes so you'll need an addMe() in themanager. It sounds like you know what your doing so w/e you choose should be right. A list with an addMe func is my recommendation and if you want only 1 active class then a function in TheManager deciding it would be good.
This maybe heavier than you need, but it sounds like you are trying to make a frame work class that supports plugins.
I would break it up into to 3 sections.
1) The FrameWork class would own the plugins.
This class is responsable for publishing interfaces supplied by the plugins.
2) A PlugIn class would own the componets that do the work.
This class is responsable for registering the exported interfaces, and binding the imported interfaces to the components.
3) The third section, the componets are the suppliers and consumers of the interfaces.
To make things extensible, getting things up and running might be broke up into stages.
Create everything.
Wire everything up.
Start everything.
To break things down.
Stop everything.
Destroy everything.
class IFrameWork {
public:
virtual ~IFrameWork() {}
virtual void RegisterInterface( const char*, void* ) = 0;
virtual void* GetInterface( const char* name ) = 0;
};
class IPlugIn {
public:
virtual ~IPlugIn() {}
virtual void BindInterfaces( IFrameWork* frameWork ) {};
virtual void Start() {};
virtual void Stop() {};
};
struct SamplePlugin :public IPlugIn {
ILogger* logger;
Component1 component1;
WebServer webServer;
public:
SamplePlugin( IFrameWork* frameWork )
:logger( (ILogger*)frameWork->GetInterface( "ILogger" ) ), //assumes the 'System' plugin exposes this
component1(),
webServer( component1 )
{
logger->Log( "MyPlugin Ctor()" );
frameWork->RegisterInterface( "ICustomerManager", dynamic_cast( &component1 ) );
frameWork->RegisterInterface( "IVendorManager", dynamic_cast( &component1 ) );
frameWork->RegisterInterface( "IAccountingManager", dynamic_cast( &webServer ) );
}
virtual void BindInterfaces( IFrameWork* frameWork ) {
logger->Log( "MyPlugin BindInterfaces()" );
IProductManager* productManager( static_cast( frameWork->GetInterface( "IProductManager" ) ) );
IShippingManager* shippingManager( static_cast( frameWork->GetInterface( "IShippingManager" ) ) );
component1.BindInterfaces( logger, productManager );
webServer.BindInterfaces( logger, productManager, shippingManager );
}
virtual void Start() {
logger->Log( "MyPlugin Start()" );
webServer.Start();
}
virtual void Stop() {
logger->Log( "MyPlugin Stop()" );
webServer.Stop();
}
};
class FrameWork :public IFrameWork {
vector plugIns;
map interfaces;
public:
virtual void RegisterInterface( const char* name, void* itfc ) {
interfaces[ name ] = itfc;
}
virtual void* GetInterface( const char* name ) {
return interfaces[ name ];
}
FrameWork() {
//Only interfaces in 'SystemPlugin' can be used by all methods of the other plugins
plugIns.push_back( new SystemPlugin( this ) );
plugIns.push_back( new SamplePlugin( this ) );
//add other plugIns here
for_each( plugIns.begin(), plugIns.end(), bind2nd( mem_fun( &IPlugIn::BindInterfaces ), this ) );
for_each( plugIns.begin(), plugIns.end(), mem_fun( &IPlugIn::Start ) );
}
~FrameWork() {
for_each( plugIns.rbegin(), plugIns.rend(), mem_fun( &IPlugIn::Stop ) );
for_each( plugIns.rbegin(), plugIns.rend(), Delete() );
}
};
Here's a minimal factory pattern implementation that I came up with in about 15 minutes. We use a similar one that uses more advanced base classes.
#include "stdafx.h"
#include <map>
#include <string>
class BaseClass
{
public:
virtual ~BaseClass() { }
virtual void Test() = 0;
};
class DerivedClass1 : public BaseClass
{
public:
virtual void Test() { } // You can put a breakpoint here to test.
};
class DerivedClass2 : public BaseClass
{
public:
virtual void Test() { } // You can put a breakpoint here to test.
};
class IFactory
{
public:
virtual BaseClass* CreateNew() const = 0;
};
template <typename T>
class Factory : public IFactory
{
public:
T* CreateNew() const { return new T(); }
};
class FactorySystem
{
private:
typedef std::map<std::wstring, IFactory*> FactoryMap;
FactoryMap m_factories;
public:
~FactorySystem()
{
FactoryMap::const_iterator map_item = m_factories.begin();
for (; map_item != m_factories.end(); ++map_item) delete map_item->second;
m_factories.clear();
}
template <typename T>
void AddFactory(const std::wstring& name)
{
delete m_factories[name]; // Delete previous one, if it exists.
m_factories[name] = new Factory<T>();
}
BaseClass* CreateNew(const std::wstring& name) const
{
FactoryMap::const_iterator found = m_factories.find(name);
if (found != m_factories.end())
return found->second->CreateNew();
else
return NULL; // or throw an exception, depending on how you want to handle it.
}
};
int _tmain(int argc, _TCHAR* argv[])
{
FactorySystem system;
system.AddFactory<DerivedClass1>(L"derived1");
system.AddFactory<DerivedClass2>(L"derived2");
BaseClass* b1 = system.CreateNew(L"derived1");
b1->Test();
delete b1;
BaseClass* b2 = system.CreateNew(L"derived2");
b2->Test();
delete b2;
return 0;
}
Just copy & paste over an initial Win32 console app in VS2005/2008. I like to point out something:
You don't need to create a concrete factory for every class. A template will do that for you.
I like to place the entire factory pattern in its own class, so that you don't need to worry about creating factory objects and deleting them. You simply register your classes, a factory class gets created by the compiler and a factory object gets created by the pattern. At the end of its lifetime, all factories are cleanly destroyed. I like this form of encapsulation, as there is no confusion over who governs the lifetime of the factories.