我一直在网上阅读和搜索一段时间,但还没有找到一个很好的解决方案。这就是我想要做的事情:
我正在编写一个定义抽象基类的库 - 我们称之为 IFoo 。
class IFoo {
public:
virtual void doSomething() = 0;
virtual ~IFoo() {}
};
该库还定义了几个实现 - 让我们称之为 FooLibOne 和 FooLibTwo 。
为了封装创建过程并根据某些运行时参数决定使用哪个具体实现,我使用工厂 FooFactory 将std :: string映射到工厂方法(在我的例子中是boost: :功能,但这不应该是这里的重点)。它还允许注册新的工厂方法。它看起来像这样:
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_;
};
现在,我直接在 FooFactory 的构造函数中添加了库提供的实现(FooLibOne,FooLibTwo) - 因此它们始终可用。一些库代码使用FooFactory初始化某些对象等。到目前为止,我已经避免使用Singleton模式用于工厂,因为tee模式经常被争论,我不确定,Singleton模式的不同实现如何工作与可能的多个共享库等结合使用。
然而,绕过工厂可能有点麻烦,我仍然认为,这是Singleton模式可以很好用的一个例子。特别是如果我考虑的话,库的用户应该能够添加更多 IFoo 的实现,这些实现也应该可以被(现有的)库代码访问。当然,依赖注入 - 意思是我通过构造函数传递工厂的实例 - 可以做到这一点(现在就做)。但是如果我想要更灵活并引入第二层动态对象创建,这种方法就会失败。含义:我想在动态创建的对象中动态创建对象(参见上文)(比如抽象基类的实现 IBar - BarOne 和 BarTwo - 再次通过工厂 BarFactory )。
让我们说 BarOne 需要 IFoo 对象,但 BarTwo 则不需要。在任何情况下,我仍然必须向 BarFactory 提供 FooFactory ,因为其中一个 IBar 实现可能需要它。拥有全球可访问的工厂可以缓解这个问题,我不会被迫预测,特定接口的实现可能需要哪些工厂。另外,我可以直接在实现的源文件中注册创建方法。
FooFactory::Instance().registerCreator("new_creator", boost::bind(...));
既然我认为这是一个好主意,那么实施它的正确方法是什么?我想采用模板化的方法,比如来自 Modern C ++ Design 的 SingletonHolder (另见Loki库)来包装工厂。但是,我宁愿把它作为迈耶的单身人士来实现。但我仍然认为共享库会出现问题。该解决方案应与GCC(最好是MSVC)一起使用。从设计的角度来看,我也对其他想法持开放态度,但请避免常见的“单身人士是邪恶的”。 ; - )
提前致谢。
答案 0 :(得分:0)
希望76行代码能说几句话 - (使用这些功能的C ++ 11版本而不是增强版本,但无论如何它们几乎相同)
我会将 factory(ies)的定义和 creators 的定义放在相同(或附近)的范围内,以便每个创建者都可以“看到”他们的任何依赖工厂 - 避免过多地绕过工厂,避免单身人士
汽车与汽车警报器:
class ISiren {};
class Siren : public ISiren
{
public:
Siren() { std::cout << "Siren Created" << std::endl; }
};
class ICar{};
class EstateCar : public ICar
{
public:
EstateCar() { std::cout << "EstateCar created" << std::endl;}
};
class PoliceCar : public ICar
{
std::shared_ptr<ISiren> siren;
public:
PoliceCar( std::shared_ptr<ISiren> siren)
: siren( siren )
{
std::cout << "PoliceCar created" << std::endl;
}
};
工厂:
typedef std::function< std::shared_ptr<ICar> () > CreatorType;
class CarFactory
{
std::map<std::string, CreatorType> creators;
public:
void AddFactory( std::string type, CreatorType func )
{
creators.insert( std::make_pair(type, func) );
}
std::shared_ptr<ICar> CreateCar( std::string type )
{
CreatorType& create( creators[type] );
return create();
}
};
class SirenFactory
{
public: // Simple factory creating 1 siren type just for brevity
std::shared_ptr<ISiren> CreateSiren() { return std::make_shared<Siren>(); }
};
“工厂根”(主要功能,无论工厂在何处定义):
int main()
{
CarFactory car_factory; // Car factory unaware of Siren factory
SirenFactory siren_factory;
auto EstateCarLambda = []() {
return std::make_shared<EstateCar>();
}; // Estate car lambda knows nothing of the Siren Factory
auto PoliceCarLambda = [&siren_factory]() {
return std::make_shared<PoliceCar>( siren_factory.CreateSiren() );
}; // Police car creation lambda using the Siren Factory
car_factory.AddFactory( "EstateCar", EstateCarLambda );
car_factory.AddFactory( "PoliceCar", PoliceCarLambda );
std::shared_ptr<ICar> car1 = car_factory.CreateCar( "EstateCar" );
std::shared_ptr<ICar> car2 = car_factory.CreateCar( "PoliceCar" );
}