2015-04-28 77 views
4

我有基類DataProcessor。它是一些座標系統中位置計算器的基類。因此,例如,它可以具有如下的後代:SphericDataProcessor,CartesianDataProcessor。基類爲CookedDataCatalogue,它是某些對象位置的容器的基類。因此,每個DataProcessor應該能夠將其數據輸入到每個CookedDataCatalogue。我可以想像這樣的事情:派生類依賴函數

class CookedDataCatalogue 
{ 
    virtual void Transform(DataProcessor* dp) = 0; 

    virtual void PutData(???) = 0; 
} 


class CookedDataCatalogue1 : public CookedDataCatalogue 
{ 
    void Transform(DataProcessor* dp) override 
    { 
     dp->TransformTo(this); 
    } 
} 

class CookedDataCatalogue2 : public CookedDataCatalogue 
{ 
    ... 
} 

class CookedDataCatalogue3 ... 

class DataProcessor 
{ 
    virtual void Process() = 0; 

    virtual void TransformTo(CookedDataCatalogue1* c) = 0; 
    virtual void TransformTo(CookedDataCatalogue2* c) = 0; 
    virtual void TransformTo(CookedDataCatalogue3* c) = 0; 
} 

但我不喜歡它。首先void Transform(DataProcessor*)從基類遷移到所有孩子**。其次,如果我將它構建爲庫,其他用戶不能添加他自己的CookedDataUserCatalogue,因爲他不能添加另一個void TransformTo(CookedDataUserCatalogue)。第三,我不知道如何編寫函數PutData(),因爲每個目錄使用他自己的數據來包含。它應該模板化嗎?

什麼是解決方案?有沒有我錯過的編程模式?

+1

在網上搜索「double dispatch pattern C++」。 –

+0

我錯了:不是煮熟的多餘!?您只需要一個'DataProcessorInterface' –

+0

目錄可以由其他人提供,並且DataProcessor不僅可以放入數據,還可以在其中進行搜索。 – DoctorMoisha

回答

1

有兩種方法可以做到這一點,以及在評論中提到的雙重分派模式:

基線

首先是您所指定的「基線」組座標的。爲了首先轉換爲核心集,然後從中轉換。

優點:您只需編寫toBaselinefromBaseline用於任意數量的不同DataProcessor s。添加新的DataProcessor與創建它然後將轉換寫入核心集和從中寫入轉換一樣簡單。

缺點:性能會受損,因爲在大多數情況下您會進行兩次轉換。準確性可能因代表或轉換中的損失而受損。

變壓器對象

創建一個對象轉換從DataProcessorDataProcessor的接口。

爲每個受支持的轉換創建該接口的實例。

有一個實用程序類,它具有源和目標對的映射到要使用的正確轉換。調用該實用程序類上的方法以根據需求執行轉換。

優點:不必浪費多次轉換。

缺點:n^2 Transform對象需要創建,其中n是不同的DataProcessor對象的數量。創建新的DataProcessor時,您需要爲每個添加的DataProcessor編寫並添加Transform對象。缺少Transform s將在運行時檢測不到編譯時間。