English 中文(简体)
C++中的工厂模式——做得正确吗?
原标题:Factory Pattern in C++ -- doing this correctly?

我对“设计模式”相对陌生,因为它们是在正式意义上被提及的。我做专业人士的时间不长,所以我对这方面还很陌生。

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

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

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

我认为工厂真的需要成为基类的包装器,而不是充当工厂的Base,这是正确的吗?

最佳回答

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

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

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

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

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

class MyFactory
{
public:
    static MyInterface* CreateImplementation(...);
};
问题回答

我不得不同意你的看法。面向对象编程最重要的原则之一可能是拥有对一段代码的作用域(无论是方法、类还是命名空间)负有单一责任。在您的情况下,基类的作用是定义接口。向该类添加工厂方法违反了这一原则,为一个充满shi…麻烦的世界打开了大门。

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

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

小心客户端代码如何传达它想要的实现类型:这是重新引入工厂想要隐藏的依赖关系的一种常见方式。

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

当接口只是用于隐藏实现详细信息,并且基本接口只有一个实现时,可以将它们耦合。在这种情况下,工厂函数只是实际实现的构造函数的新名称。

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

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





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?