make_unique, фабричный метод или другой дизайн для клиентского API?

У нас есть библиотека, которая публикует абстрактный базовый класс:

(иллюстративный псевдокод)


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

Но это, очевидно, представляет большую проблему — вы на самом деле пытаетесь построить ReaderApiне PcapReader, Очевидное решение этой проблемы заключается в реализации virtual constructor идиома или использование фабричного строительства. Но виртуальная конструкция кажется мне слишком сложной для такого использования.

1

Решение

Для меня, два варианта, которые нужно рассмотреть, это ваш текущий подход или уровень пространства имен с подходящим названием free function. Кажется, нет нужды в перечисленной фабрике, если нет подробностей, о которых вы не упомянули.

С помощью make_unique раскрывает детали реализации, поэтому я бы определенно не предлагал такой подход.

1

Другие решения


По вопросам рекламы [email protected]