dimanche 8 mars 2015

Visitor pattern with default for properties

I would like to get folks' thoughts on the following approach, and perhaps even suggest better alternatives.


I have a weather simulation, and I want to be able to calculate specific properties as the simulation progresses. Suppose I have a Base Class WeatherSim from which different types of simulations derive. So I may have a ConstantTemperatureWeatherSim or ConstantPressureWeatherSim, etc..


In the case of ConstantTemperatureWeatherSim I may be interested in how the average barometric pressure changes with time (iterations in the actual simulation), and so on. I may also run the same simulations, where I want to monitor other properties, such as average velocity field vector, or some arbitrary quantity which I desire.


The thing is, I need to calculate the properties in the most efficient way possible, since these simulations are very computationally expensive. This means that while I can have a vector of property calculating functions, like this:



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

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

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


This approach is very inefficient. For the case of say, average pressure, I can loop though all elements in the model and get the pressure property on every iteration. A much more effective approach is to keep a running average.


The thing is, I don't want to pollute my class with every possible calculable quantity (and frankly I can't even if I wanted to, since I don't know what weird property a user may want to calculate).


My solution to this problem was to use somewhat of a visitor pattern. My WeatherSim is a Visitable object, and the property I want to calculate is my Visitor. I store a vector of Visitors in my WeatherSim and each iteration I call the Visitors to do their thing. Each visitor will accept a reference to WeatherSim and so they can store their running average internally.


In my mind that is a good way of solving this issue, except there are two other things I need to resolve, which is why I'm here.




  1. Some properties are needed to perform calculations in a specific simulation. So for example, I may need to use pressure in my ConstantTempWeatherSim as part of the algorithm. Should I just keep a running average of the required property separately from my Visitors and use those to augment the properties already computed by the WeatherSim? Or should I have a private vector of PropertyVisitors that I use for the necessary properties and have the user add anything else they need to a separate queue? Is there some other way?




  2. After each iteration, WeatherSim calls Observers to log the desired information. What's the best way of getting the data from the PropertyVisitors to the Observer? I don't think it would be wise to pass in a vector of references to the PropertyVisitors themselves to the Observers. I was thinking that in my SimEvent class, which contains information on the event, I could get the values from all the PropertyVisitors and store them in a vector in SimEvent. Or am I barking up the wrong tree?




Perhaps the visitor pattern isn't the best approach to this. I would appreciate thoughts on how to approach this problem.


Thank you all in advance!


Aucun commentaire:

Enregistrer un commentaire