访客模式,默认为属性

时间:2015-03-08 20:17:29

标签: c++ oop design-patterns

我想找人们#39;关于以下方法的想法,甚至可能提出更好的替代方案。

我有一个天气模拟,我希望能够在模拟过程中计算出特定的属性。假设我有一个基类WeatherSim,从中可以得到不同类型的模拟。所以我可能有ConstantTemperatureWeatherSimConstantPressureWeatherSim等等。

ConstantTemperatureWeatherSim的情况下,我可能对平均气压如何随时间变化(实际模拟中的迭代)等感兴趣,等等。我也可以运行相同的模拟,我想监视其他属性,例如平均速度场矢量,或者我想要的任意数量。

问题是,我需要以最有效的方式计算属性,因为这些模拟非常计算成本高。这意味着虽然我可以有一个属性计算函数的向量,如下所示:

class ConstTempWeatherSim {
    std::vector<std::function<double(Model&)>> properties;

    void Iterate() {
     // Perform calculations...

     // Calculate properties
     for(auto& property : properties)
          property(model);
}

这种方法效率很低。对于平均压力的情况,我可以循环模型中的所有元素,并在每次迭代时获得压力属性。更有效的方法是保持平均运行。

问题是,我不想以尽可能可计算的数量污染我的班级(坦率地说,即使我想要,我也不能,因为我不知道什么是奇怪的财产用户可能想要计算)。

我对此问题的解决方案是使用某种访问者模式。我的WeatherSimVisitable对象,我要计算的属性是Visitor。我在Visitors中存储了WeatherSim的向量,每次迭代我都会调用Visitors来做他们的事情。每位访问者都会接受WeatherSim的引用,因此他们可以在内部存储其平均值。

在我看来,这是解决这个问题的好方法,除了我需要解决的其他两件事,这就是我在这里的原因。

  1. 在特定模拟中执行计算需要一些属性。因此,例如,我可能需要在ConstantTempWeatherSim中使用压力作为算法的一部分。我应该将所需属性的运行平均值与Visitors分开保存,并使用它们来扩充WeatherSim已经计算过的属性吗?或者我应该有一个PropertyVisitors的私有向量,我用于必要的属性,并让用户将他们需要的任何东西添加到一个单独的队列?还有其他方式吗?

  2. 每次迭代后,WeatherSim会调用Observers来记录所需的信息。从PropertyVisitorsObserver获取数据的最佳方法是什么?我不认为将PropertyVisitors本身的引用向量传递给Observers是明智的。我想在我的SimEvent课程中,其中包含有关该事件的信息,我可以从所有PropertyVisitors获取值,并将它们存储在SimEvent中的向量中。还是我在错误的树上吠叫?

  3. 也许访客模式不是最佳方法。我很感激如何解决这个问题。

    提前谢谢大家!

1 个答案:

答案 0 :(得分:0)

访客模式在这里感觉有点奇怪。通常使用访客模式,访问者需要了解所有不同的可访问类型。这就是它如何实现对访客类型和可访问类型的双重调度。如果不同的可访问类型相当静态,但您可能需要在将来添加新访问者,这是合适的。在你的情况下,这意味着属性需要知道所有不同类型的WeatherSim,这对我来说听起来不太合适。我不会期待那种耦合。

但是基于我有限的理解来回答你的具体问题:

  1. 我建议只有一个属性列表,但某些属性可能需要注册为特定模拟的特殊属性之一。特殊属性的寄存器只存储对属性的引用。然后,用户可以选择他们想要注册哪个属性作为特殊的“压力”属性。也许特殊的Pressure属性需要符合要注册的某些“压力”接口/模板。
  2. 通常有两种方法可以运行Observers push或pull。您可以将一组数据推送到所有Observers,这是我认为您建议通过将值复制到SimEvent中。或者你只是告诉观察者一些事情发生了变化,观察者有责任从模拟中提取他们需要的信息。我认为两者都是有效的运行方式,哪种方式将取决于您的特定要求。推送模型可能效率低下,因为即使某个特定观察者可能对某些数据不感兴趣,您也必须推送所有数据。拉模型效率低,因为通信分两步完成,观察者可能必须找出自己确切改变了哪些数据。拉模型在观察者和模拟之间引入了更多的耦合。在推送模型中,您可能必须更改每次Observer需要新内容时推送的数据集。