2012-08-14 54 views
2

我確實有兩個類:讀者和作家。對於這兩個班我因爲數據源的抽象接口/目標應靈活:類繼承/構造的設計

class abstract_reader { 
... 
}; 

class concrete_reader : public abstract_reader { 
    DATATYPE m_data; 
... 
};  
class abstract_writer { 
... 
}; 

class concrete_writer : public abstract_writer { 
    DATATYPE m_data; 
... 
}; 

作家應具有兩種功能,讀取和寫入concrete_writer的閱讀部分的實現是一樣的concrete_reader的實現。結合這些類的好方法是什麼?

+1

我很困惑:你有一個讀者和一個作家,但作者也是一個讀者(那麼爲什麼有一個單獨的讀者?),但實際上兩者都以相同的方式實現? – 2012-08-14 13:51:41

+0

在大多數情況下,我只需要一個閱讀器,所以有一個閱讀器類是有意義的。寫作只在特殊情況下需要。 m_data與用戶隱藏,但在兩種情況下都是相同的格式。作者在大多數情況下依賴於已經在數據源中的數據。如果我有一個單獨的閱讀器和書寫器,我需要將m_data(這只是一個實現工具)從閱讀器傳遞給作者。流程如下:我讀取數據,將一些數據提供給用戶,用戶創建新數據,用戶將新數據提供給寫入器,寫入器更新數據源。 – Michael 2012-08-14 18:55:06

回答

2

你想要的是一個有點混亂,但有多種方式:

  • 從兩個抽象類派生的作家
  • 保持一個指向具體的讀者的作家
  • 抓住讀者的具體的實例,在作家
  • 從編寫器中刪除讀取功能,並創建可以讀取和寫入的第三個類。

就我個人而言,我會按照最後的方式,那麼你將有一整套的只讀,只寫,以及兩者兼而有之。

+0

我會說最後一個選項涵蓋了不同的主題。它說「與前幾個」給出的方式「相比,」要做什麼「。 – 2012-08-14 13:57:20

+0

@Bartek,是的,我同意。這也不是真正解決OP問題的答案,而是如何以另一種方式做到這一點的建議。但是,有一個替代方案總是很好的;) – SingerOfTheFall 2012-08-14 15:41:18

1

爲什麼作者想知道如何閱讀?也許你應該考慮第三堂課,結合雙方的閱讀和寫作功能。

如果你相信它的美好,只是獲得來自abstract_readerabstract_writer作家。只要它們是正確實現的接口(例如沒有字段),一切都應該正常工作。

呵呵,也許這將是很好的整合模板(我已經注意到神祕DATATYPE

1
class concrete_writer : public abstract_writer, public abstract_reader { 
public: 
    void read() { // or whatever the proper override is for abstract_reader 
     reader.read(); 
    } 
private: 
    concrete_reader reader; 
}; 

但是,正如@Bartek指出的,有一個名爲「writer」的類也讀取這個類似乎很奇怪。

1

首先,如果它只是一個writer,它不應該知道如何閱讀。當你在屏幕上實現一個編寫器時會發生什麼 ?儘管如此,除了ReaderWriter之外,還有一個 ReaderWriter,這是一個非常合理的選擇,並且會產生相同的問題。

我會做到這一點的辦法,首先,定義ReaderWriter作爲 接口,來自ReaderWriter繼承:

class Reader 
{ 
private: 
    // Pure virtual functions to the implementation... 
public: 
    virtual ~Reader() {} 
    // Interface... 
}; 

class Writer 
{ 
private: 
    // Pure virtual functions to the implementation... 
public: 
    virtual ~Writer() {} 
    // Interface... 
}; 

class ReaderWriter : public virtual Reader, public virtual Writer 
{ 
    // Just joins the two; adds nothing new of its own 
}; 

注意虛擬繼承。當你擴展接口時,這通常應該是默認值。一旦你得到了,你可以(通常) 使用混入了實現:

class ConcreteReader : public virtual Reader 
{ 
    // Overrides for the pure virtual functions, + any data needed. 
public: 
    ConcreteReader(); // Or with parameters, as needed. 
}; 

class ConcreteWriter : public virtual Writer 
{ 
    // Overrides for the pure virtual functions, + any data needed. 
public: 
    ConcreteWriter(); // Or with parameters, as needed. 
}; 

class ConcreteReaderWriter : public ReaderWriter, public ConcreteReader, public ConcreteReaderWriter 
{ 
}; 
接收一個 Reader*可以閱讀

客戶代碼;客戶端代碼 收到Writer*可寫;而接收到 ReaderWriter的客戶端代碼也可以做。當然,如果客戶端有一個 Reader*,它總是可以嘗試到dynamic_cast它到Writer*ReaderWriter*,如果dynamic_cast成功,它也可以寫入。

編輯:我忘了提及:這種技術被稱爲mixins。

+0

這是一個非常有用的答案 – Michael 2012-08-15 12:51:44