我不知道这是否有正式名称,但我一直在玩我喜欢称之为“自我工厂”的模式。基本上,当抽象基类充当自己的工厂时。让我解释一下:
我的系统中有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");
从可用性角度和架构角度来看,每种方法的优缺点是什么?
答案 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。