我们有一个发布抽象基类的库:
(说明性的伪代码)
/include/reader_api.hpp
class ReaderApi
{
public:
static std::unique_ptr <ReaderApi> CreatePcapReader ();
virtual ~ReaderApi() = 0;
};
在库实现中,有一个
ReaderApi
的具体实现可以读取pcap文件:/lib/pcap_reader_api.cpp
class PcapReaderApi
:
public ReaderApi
{
public:
ReaderApi() {};
};
客户端代码应通过工厂方法实例化以下
PcapReaderApi
对象之一:std::unique_ptr <ReaderApi> reader = ReaderApi::CreatePcapReader ();
在几个层面上,这对我来说感觉很差。
首先,factory方法应该是免费的,而不是
static
的ReaderApi
成员。它是static
的ReaderApi
成员,以明确显示 namespace 。无论哪种方式,我都能看到优点和缺点。随时对此发表评论,但这不是我的主要论点。其次,我的直觉告诉我,我应该使用
std::make_unique
而不是完全调用工厂方法。但是由于实际对象是实现细节,而不是公共(public) header 的一部分,因此客户端不需要make_unique
。就可理解性和代码维护而言,最简单的解决方案似乎是我上面已经提出的解决方案,除非有我不知道的更好的解决方案。在这里,性能不是主要考虑因素,因为由于该对象的性质,在启动时仅实例化一次。
考虑到代码的清晰性,可理解性和可维护性,是否有比我这里设计的更好的方法来设计这些对象的创建?
我考虑了以下两种替代方法。
我考虑过的另一种方法是将某种标识符传递给通用的
Create
函数。标识符将指定客户希望构造的对象的类型。可能是enum class
,如下所示:enum class DeviceType
{
PcapReader
};
std::unique_ptr <ReaderApi> CreateReaderDevice (DeviceType);
但是我不确定这样做与仅使create函数自由和显式有关的意义:
std::unique_ptr <ReaderApi> CreatePcapReader ();
我还考虑过在
DeviceType
的构造函数中指定ReaderApi
参数:class ReaderApi
{
public:
ReaderApi (DeviceType type);
virtual ~ReaderApi() = 0;
};
这将启用
make_unique
惯用语:std::unique_ptr <ReaderApi> reader = std::make_unique <ReaderApi> (DeviceType::PcapReader);
但这显然会带来一个大问题-您实际上是在尝试构造
ReaderApi
,而不是PcapReader
。解决此问题的明显方法是实现virtual constructor
习惯用法或使用工厂构造。但是,对于我来说,虚拟建筑在工程上似乎过度设计了。 最佳答案
对我来说,要考虑的两个选项是您当前的方法,或者是命名空间级别(适当地命名为free function)。除非没有您提到的细节,否则似乎不需要枚举工厂。
使用make_unique
会公开实现细节,因此我绝对不会建议这种方法。
关于c++ - make_unique,工厂方法或客户端API的不同设计?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26890913/