2

我一直在阅读和搜索网络一段时间,但还没有找到一个好的解决方案。这是我想要做的:

我正在编写一个定义抽象基类的库 - 我们称之为IFoo

class IFoo {
    public:
        virtual void doSomething() = 0;
        virtual ~IFoo() {}
};

该库还为此定义了几个实现——我们称它们为FooLibOneFooLibTwo

为了封装创建过程并根据某些运行时参数决定使用哪个具体实现,我使用工厂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_;
};

现在,我直接在FooFactory的构造函数中添加了库提供的实现(FooLibOne、FooLibTwo)——因此它们始终可用。一些库代码使用 FooFactory 来初始化某些对象等。到目前为止,我一直避免对工厂使用单例模式,因为 tee 模式经常被争论,我不确定单例模式的不同实现如何工作结合可能的多个共享库等。

然而,在工厂之间传递可能有点麻烦,我仍然认为,这是单例模式可能有用的场合之一。特别是如果我考虑到,库的用户应该能够添加更多的IFoo实现,这些实现也应该可供(已经存在的)库代码访问。当然,依赖注入——意味着我通过构造函数传递了一个工厂的实例——可以做到这一点(现在就这样做)。但是,如果我想更加灵活并引入第二层动态对象创建,这种方法就会失败。含义:我想在动态创建的对象(比如抽象基类IBar - BarOneBarTwo - 再次通过工厂BarFactory)。

假设BarOne需要一个IFoo对象,但BarTwo不需要。无论如何,我仍然必须将 FooFactory 提供给BarFactory因为其中一个IBar实现可能需要它。拥有全球可访问的工厂将缓解这个问题,并且我不会被迫预见特定接口的实现可能需要哪些工厂。此外,我可以直接在实现的源文件中注册创建方法。

FooFactory::Instance().registerCreator("new_creator", boost::bind(...));

既然我认为这是一个好主意,那么实施它的正确方法是什么?我打算采用模板化方法,例如Modern C++ Design中的SingletonHolder(另请参见Loki库)来包装工厂。但是,我宁愿将其实现为 Meyer 的 Singleton。但我仍然认为共享库会有问题。该解决方案应与 GCC(最好是 MSVC)一起使用。从设计的角度来看,我也对其他想法持开放态度,但请避免常见的“单身人士是邪恶的”-咆哮。;-)

提前致谢。

4

1 回答 1

0

希望 76 行代码能说的不仅仅是几句话——(使用这些功能的 C++11 版本而不是增强功能,但无论如何它们几乎相同)

我会将工厂的定义和创建者的定义放在同一(或附近)范围内,以便每个创建者都可以“看到”他们的任何依赖工厂 - 避免也需要传递工厂很多,并避免单例

汽车和警报器:

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" );
}
于 2012-04-01T20:58:49.730 回答