我有一個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