C ++中的工厂模式 - 正确执行此操作?

时间:2011-02-14 12:47:00

标签: c++ design-patterns interface factory-pattern

我对“设计模式”相对较新,因为它们在正式意义上被提及。我很长时间没有成为一名专业人士,所以我对此很陌生。

我们有一个纯虚拟接口基类。这个接口类显然是提供了派生子进程应该做什么功能的定义。软件中的当前用法和情况决定了我们想要使用什么类型的派生子,因此我建议创建一个包装器,它将传达我们想要的派生子类型,并返回指向新派生对象的Base指针。据我所知,这个包装器是一个工厂。

好吧,我的一位同事在Base类中创建了一个静态函数来充当工厂。这有两个原因导致我麻烦。首先,它似乎打破了Base类的接口性质。我认为界面本身需要知道从中衍生出来的孩子,这是错误的。

其次,当我尝试在两个不同的Qt项目中重用Base类时,会导致更多问题。一个项目是我实现第一个(可能只是这个类的真正实现......虽然我想对其他两个具有几个不同派生类的特性使用相同的方法)派生类,第二个是实际最终将使用我的代码的应用程序。在我编写代码时,我的同事创建了一个派生类,作为真实应用程序的测试人员。这意味着我必须将他的标题和cpp文件添加到我的项目中,这似乎是错的,因为我在实现我的部分时甚至没有使用他的代码用于项目(但是当它完成时他将使用我的)。

我认为工厂真的需要成为Base类的包装而不是作为工厂的Base吗?

5 个答案:

答案 0 :(得分:15)

您不希望将接口类用作工厂类。首先,如果它是一个真正的接口类,则没有实现。其次,如果接口类确实定义了一些实现(除了纯虚函数),那么现在创建一个静态工厂方法会强制每次添加子类实现时重新编译基类。

实现工厂模式的最佳方法是将您的接口类与工厂分开。

下面是一个非常简单(不完整)的例子:

class MyInterface
{
public:
    virtual void MyFunc() = 0;
};

class MyImplementation : public MyInterface
{
public:
    virtual void MyFunc() {}
};

class MyFactory
{
public:
    static MyInterface* CreateImplementation(...);
};

答案 1 :(得分:4)

我必须同意你的看法。面向对象编程最重要的原则之一可能是对于一段代码的范围(无论是方法,类还是命名空间)都有single responsibility。在您的情况下,您的基类用于定义接口。在该类中添加工厂方法,违反了这一原则,打开了通往石头世界的大门......麻烦。

答案 2 :(得分:3)

是的,接口(基类)中的静态工厂方法要求它知道所有可能的实例化。这样,您就无法获得Factory Method模式带来的任何灵活性。

Factory应该是一段独立的代码,由客户端代码用于创建实例。您必须在程序中决定某处要创建的具体实例。 Factory Method允许您避免通过客户端代码分散相同的决策。如果以后要更改实施(或者例如进行测试),则只需要编辑一个地方:例如,这可能是一个简单的全局变化,通过条件编译(通常用于测试),甚至通过依赖注入配置文件。

请注意客户端代码如何传达它想要的实现类型:这不是重新引入工厂隐藏的依赖项的不常见方式。

答案 3 :(得分:2)

在一个班级看到工厂成员的功能并不罕见,但这让我的眼睛流血了。它们的使用经常与named constructor idiom的功能混淆。将创建函数移动到单独的工厂类将为您在测试期间交换工厂提供更大的灵活性。

答案 4 :(得分:1)

如果界面仅用于隐藏实施细节,并且只有一个实现的Base接口永远,那么可以将它们结合起来。在这种情况下,工厂函数只是实际实现的构造函数的新名称。

然而,这种情况很少见。除非明确设计只有一个实现,否则最好假设在某个时间点存在多个实现,如果仅用于测试(如您所发现的那样)。

因此通常最好将Factory部分拆分为单独的类。

相关问题