2015-04-28 70 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将在运行时检测不到编译时间。