我有一个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种方法就可以获得大量的接口。
没有更好的方法来组织接口来获得这样的东西吗?
我也在考虑使用Lambda表达式,但在屏幕后面,这与仅有1个方法的许多接口几乎相同。
任何想法?
完全一致,书自然想到的可能有书号和价格。鉴于一本特定的书,我想询问它是否可购买,价格是多少,如果它有一个ISBN和那个ISBN值是什么......这些操作语义上属于'IBook'接口。从另一个角度看,拥有一个'ISBNGetter'接口似乎意味着不同的对象可能有ISBN,但只有书有它。没有任何情况下你会在不是'IBook'的对象上使用额外的接口。 – 2010-11-19 12:39:53
@dribeas:是的,虽然'IISBNGetter'从'IBook'派生出来可能比它的价值更麻烦,即使你使用额外的接口。不过,我认为ISBN-13与UPC兼容。如果是这样,那么'IUPCGetter'会更普遍,'IBuyable'肯定是。 “IBuyable”可能是一个有价值的界面,无论它是否定义了所有的书籍都实现了它,或者只有一些。 – 2010-11-19 12:46:01