У меня есть модуль C ++, который должен получать информацию от других классов, не зная этих классов.Очевидный подход заключается в использовании интерфейсов.
Позвольте мне привести пример.Предположим, у меня есть библиотека, которая управляет книгами, и все книги имеют свои собственные характеристики и функциональные возможности, и чтобы библиотека могла получить характеристику из книги или выполнить функцию, в книге должен быть реализован интерфейс.Например:
class Library
{
public:
void addBook(IBook &book);
};
class IBook
{
public:
string getAuthor() = 0;
string getTitle() = 0;
string getISBNCode() = 0;
size_t getNofPages() = 0;
size_t getNofImages() = 0;
double getPrice() = 0;
void printBook() = 0;
void convertToPdf() = 0;
};
К сожалению, нет смысла применять все эти методы для всех видов книг.
- В некоторых книгах нет изображений (поэтому я нене хочу реализовывать getNofImages ())
- Некоторые книги не имеют ISBN-кода
- Некоторые книги нельзя купить, поэтому у них нет цены
- Некоторые книги не могут быть напечатаны
- Некоторые книги не могут быть преобразованы в PDF
Поскольку у меня только 1 интерфейс, я вынужден реализовать все для всех книг ивернуть 0, вернуть "" или ничего не делать в реализации, если это не имеет значения.
Альтернативой может быть разделение этих интерфейсов на множество интерфейсов, например:
class IBook
{
public:
string getAuthor() = 0;
string getTitle() = 0;
size_t getNofPages() = 0;
};
class IISBNGetter
{
public:
string getISBNCode() = 0;
};
class IImagesGetter
{
public:
size_t getNofImages() = 0;
};
class IBuyable
{
public:
double getPrice() = 0;
};
class IPrintable
{
public:
void printBook() = 0;
};
class IConvertible
{
public:
void convertToPdf() = 0;
};
Классы книг затемнужно только реализовать интерфейсы, которые они действительно хотят поддерживать.
Добавление книги в библиотеку становится примерно таким:
bookid = myLibrary->addBook (myBook);
myLibrary->setISBNGetter (bookid, myBook);
myLibrary->setImageGetter (bookid, myBook);
myLibrary->setBuyable (bookid, myBook);
Преимущество наличия различных интерфейсов состоит в том, что они понятныдля библиотеки, которая поддерживает что, и этоникогда не возникает риск вызова чего-то, что просто не поддерживается.
Однако, поскольку каждая книга может иметь любую возможную комбинацию характеристик / функций, я получаю множество интерфейсов только с одним методом.
Разве нет лучшего способа организовать интерфейсы для получения чего-то подобного?
Я также думал об использовании лямбда-выражений, но за экранами это почти то же самое, что иметь много интерфейсов только с 1Метод.
Есть идеи?