Некоторое время я читал и искал в Интернете, но не нашел хорошего решения.Вот что я хочу сделать:
Я пишу библиотеку, которая определяет абстрактный базовый класс - давайте назовем его IFoo .
class IFoo {
public:
virtual void doSomething() = 0;
virtual ~IFoo() {}
};
Библиотека также определяетпара реализаций для этого - давайте назовем их FooLibOne и FooLibTwo .
Для того, чтобы инкапсулировать процесс создания и решить, какая конкретная реализация используется в зависимости от некоторого параметра времени выполненияЯ использую фабрику FooFactory , которая отображает std :: string на методы фабрики (в моем случае boost :: function, но это не должно быть здесь).Это также позволяет регистрировать новые фабричные методы.Это выглядит примерно так:
class FooFactory {
public:
typedef boost::function<IFoo* ()> CreatorFunction;
IFoo* create(std::string name);
void registerCreator(std::string name, CreatorFunction f);
private:
std::map<std::string, CreatorFunction> mapping_;
};
На данный момент я добавил реализации, предоставленные (FooLibOne, FooLibTwo) библиотекой непосредственно в конструктор FooFactory - таким образом, они всегда доступны.В некотором коде библиотеки для инициализации определенных объектов используется FooFactory и т. Д. До сих пор я воздерживался от использования шаблона Singleton для фабрик, поскольку шаблон tee обсуждается достаточно часто, и я не был уверен, как будут работать различные реализации шаблона Singleton.в сочетании с, возможно, несколькими общими библиотеками и т. д.
Однако обход заводов может быть немного громоздким, и я все еще думаю, что это один из случаев, когда шаблон Singleton мог бы быть полезным.Особенно, если учесть, что пользователи библиотеки должны иметь возможность добавить больше реализаций IFoo , которые также должны быть доступны для (уже существующего) кода библиотеки.Конечно, Dependency Injection - то есть я передаю экземпляр фабрики через конструктор - может сделать свое дело (и делает это сейчас).Но этот подход не работает, если я хочу быть еще более гибким и ввести второй уровень создания динамических объектов.Значение: я хочу динамически создавать объекты (см. Выше) в динамически создаваемых объектах (скажем, реализации абстрактного базового класса IBar - BarOne и BarTwo - снова черезфабрика BarFactory ).
Допустим, BarOne требует IFoo объекта, но BarTwo этого не делает.Я все еще должен предоставить FooFactory BarFactory в любом случае, поскольку одна из IBar реализаций может нуждаться в этом.Наличие глобально доступных фабрик могло бы смягчить эту проблему, и я не был бы вынужден предвидеть, какие фабрики могут понадобиться при реализации определенного интерфейса.Кроме того, я мог бы зарегистрировать методы создания непосредственно в исходном файле реализаций.
FooFactory::Instance().registerCreator("new_creator", boost::bind(...));
Поскольку я думаю, что это хорошая идея, каким будет правильный способ ее реализации?Я собирался использовать шаблонный подход, такой как SingletonHolder из Modern C ++ Design (см. Также Loki library), чтобы обернуть фабрики.Однако вместо этого я предпочел бы реализовать его как синглтон Майера.Но я все еще думаю, что будут проблемы с общими библиотеками.Решение должно работать с GCC (и предпочтительно MSVC).Я также открыт для других идей с точки зрения дизайна, но, пожалуйста, избегайте распространенных грантов "Singletons are evil".; -)
Заранее спасибо.