“自我造型”模式

时间:2009-06-24 21:55:27

标签: c++ factory

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

我的系统中有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");

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

3 个答案:

答案 0 :(得分: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();
};

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

答案 1 :(得分:2)

工厂有两个常见用途:

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

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

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

答案 2 :(得分:1)

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

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

哦,当界面有一个创建它类型对象的方法时,它被称为factory method pattern