3

我不知道这个有没有正式的名称,但我一直在玩我喜欢称之为“自我工厂”的模式。基本上,这是一个抽象基类充当自己的工厂的时候。让我解释:

我的系统中有 Foo 对象和 Bar 对象,它们通过接口 FooInterface 和 BarInterface 使用。我需要为我的客户提供正确类型的 Foo 和 Bar。在编译时决定创建哪个具体的 Foo 对象。例如,如果你在 win32 上编译,你只想创建 Win32Foo 对象,如果你在 OSX 上编译,你只想创建 OSXFoo 对象等等。但是,创建哪个具体的 Bar 对象是在运行时根据键字符串决定的。

现在,我的问题是关于实施该方案的最佳方式。我想出的一种方法是使用常规工厂:

shared_ptr<FooInterface> foo = FooFactory::create();
shared_ptr<BarInterface> happyBar = BarFactory::create("Happy");
shared_ptr<BarInterface> sadBar = BarFactory::create("Sad");

另一种方法是使用我所说的“自我工厂”:

shared_ptr<FooInterface> foo = FooInterface::create();
shared_ptr<BarInterface> happyBar = BarInterface::create("Happy");
shared_ptr<BarInterface> sadBar = BarInterface::create("Sad");

从可用性的角度和架构的角度来看,每种方法的优缺点是什么?

4

3 回答 3

3

我会做出改进:

shared_ptr<FooInterface> foo = Factory<FooInterface>::create();
shared_ptr<BarInterface> happyBar = Factory<BarInterface>::create("Happy");
shared_ptr<BarInterface> sadBar = Factory<BarInterface>::create("Sad");

你会声明:

template <class I>
struct Factory { };

然后对于需要工厂的每个接口,您可以这样做:

template <>
struct Factory<FooInterface>
{
    static FooInterface create();
};

这允许您将工厂实现与接口声明分开,但仍使用类型系统在编译时绑定它们。

于 2009-06-24T22:12:42.107 回答
2

工厂有两种常见用途:

1)在运行时根据参数和/或全局状态(例如配置)决定动态多态类型。你的模式就是这样做的。

2)依赖注入:不是使用静态函数来创建对象,而是使用工厂对象,以便调用者可以通过传入他们想要的任何工厂来配置返回的对象类型。这些模式都没有提供这一点。此外,您的第二种模式甚至不允许静态依赖注入(通过具有将工厂类作为模板参数的模板函数),因为接口和工厂是相同的。

因此,您的模式(以及您的常规工厂)的一个缺点是依赖注入不受真正支持。只有一个函数可以调用来获取一个 FooInterface 对象,那就是 FooInterface::create()。我不会争论为什么依赖注入是有用的,只是指出如果你用这种方式构建,你就不能使用它。

于 2009-06-24T22:04:05.040 回答
1

通常工厂负责创建整个类层次结构的对象。因此,在您的示例中,您将拥有 Win32Factory、OSXFactory 等。这样做的一个优点是您只需在工厂创建期间选择一次特定的实现(win32/unix/etc),但如果您使用类接口,您有一直提供操作系统信息。

如果您只有两个类(Foo 和 Bar),我不确定是否值得为它们创建工厂而不仅仅是使用create接口的方法。

哦,当一个接口有一个方法来创建它的类型的对象时,它被称为工厂方法模式

于 2009-06-24T22:01:08.417 回答