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

Factory Pattern in C++ — doing this correctly?

我对"设计模式"比较陌生,因为它们在形式上被提到。我已经不是一个专业人士很长时间了,所以我对这个很陌生。

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

我的一个同事在基类中创建了一个静态函数来充当工厂。这给我带来麻烦有两个原因。首先,它似乎破坏了基类的接口性质。我觉得界面本身需要了解从中衍生出来的孩子们是不对的。

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

我是否正确地认为工厂确实需要是一个围绕基类的包装器,而不是作为工厂的基础?


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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MyInterface
{
public:
    virtual void MyFunc() = 0;
};

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

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


我不得不同意你的看法。可能面向对象编程最重要的原则之一是对一段代码的范围(无论是方法、类还是名称空间)负有单一责任。在您的例子中,基类用于定义接口。在这个类中添加一个工厂方法,违反了这一原则,打开了一扇通往世界的大门。麻烦。


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

工厂应该是一段独立的代码,由客户机代码用来创建实例。您必须在程序中的某个地方决定要创建什么具体实例。工厂方法允许您避免通过客户机代码进行相同的决策。如果以后您想要更改实现(或者例如,为了测试),您只有一个地方可以编辑:这可能是一个简单的全局更改,通过条件编译(通常是为了测试),甚至通过依赖项注入配置文件。

注意客户机代码如何传递它想要的实现类型:这不是一种重新引入工厂要隐藏的依赖关系的常见方法。


在类中看到工厂成员函数并不少见,但它会让我眼睛出血。它们的使用常常与命名的构造函数习惯用法的功能混合在一起。将创建函数移动到单独的工厂类将为您提供更大的灵活性,并在测试期间交换工厂。


当接口只是为了隐藏实现细节,并且基本接口的实现只有一个时,可以将它们结合起来。在这种情况下,工厂函数只是实际实现的构造函数的一个新名称。

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

所以通常最好将工厂部件划分为单独的类。