我们有一个发布抽象基类的库:

(说明性的伪代码)

/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方法应该是免费的,而不是staticReaderApi成员。它是staticReaderApi成员,以明确显示 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/

10-11 23:06
查看更多