1

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

(说明性伪代码)


/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 ();

这在几个层面上让我感觉很恶心。

首先,工厂方法应该是免费的,而static不是ReaderApi. 它是明确命名空间的static成员。ReaderApi无论哪种方式,我都可以看到利弊。随意对此发表评论,但这不是我的主要争论点。

其次,我的直觉告诉我我应该使用std::make_unique而不是调用工厂方法。但由于创建的实际对象是一个实现细节,而不是公共标头的一部分,因此客户端无需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);

但这显然会带来一个大问题——你实际上是在尝试构建 a ReaderApi,而不是 a PcapReader。解决这个问题的明显方法是实现一个virtual constructor成语或使用工厂构造。但是对于我来说,虚拟构造似乎过度设计用于此用途。

4

1 回答 1

1

对我来说,要考虑的两个选项是您当前的方法,或者适当命名为自由函数的命名空间级别。除非有您未提及的细节,否则似乎不需要枚举工厂。

Usingmake_unique暴露了实现细节,所以我绝对不会建议这种方法。

于 2014-11-12T20:08:18.703 回答