views:

74

answers:

2

I'm looking for a pattern describing a certain situation. Maybe someone knows something and can give me a hint

Situation Object of type A, 1 : n association to objects of type B. Example: A Person and all his pets. The pet objects have an age data member. Now each person should have a data member for the average age of his pets. I don't want this information to be saved and loaded but to be computed during the loading process (all necessary information is already there, so it's kind of redundant, but I want the information in the person object).

Question So how can I do this in an object oriented way? Is there a pattern that describes this situation? My first idea was to have a class ComputedFieldsUpdater who takes a pet object and then computes all the field that have not been loaded. But I wonder if this is the right way or if there might be a more elegant solution?

Thanks for your thoughts.

+1  A: 

If you create a class for the association to type B it's fairly simple: You need some kind of list anyway. So just create a "PetList" or something like that, that has a Method "averageAge()" which computes this value from all it's pets.

Now you can access the average by calling person.getPets().averageAge().

From an object-oriented point of view the information about the average shouldn't be directly in the Person-object anyway.

Benedikt Eger
even better the average then can be cached instead of recomputed each time
MahdeTo
"From an object-oriented point of view the information about the average shouldn't be directly in the Person-object anyway." - I'm not so sure about this. Generally in OOP, some code wants to ask some class to perform the calculation for it - and not worry about internal or intermediate representations of the data. I think something like person.getPetsAverageAge() would be a suitable method for this.
harto
But this would violate the single responsibility principle. A Person class as I understand it is responsible for the representation of the abstract concept of a person. If you also make it responsible for doing calculations on associated classes then you have given it a second responsibility.Unless of course Person's only purpose is doing these calculations an not representing a person. But the the naming is highly misleading.
Benedikt Eger
A: 

Its not a Gang of Four design pattern, but the generally accepted solution when it is absolutely necessary to store data that is redundant to a calculation is to lazy-load it, and then keep a boolean value to describe whether it is still valid.

In other words:

class Person
{
List<Pet> myPets;
float averageAge;
boolean isAgeValid = false;

float getAverageAge()
{
    if(isAgeValid)
        return averageAge;
    else
        ...calculate age, save it in averageAge, set bool to true, and return derived float...
}

//all list operations should mark the bool false
void Add(Pet p)
{
    myPets.Add(p);
    isAgeValid=false;
}
}
JoshJordan
You can also have a Person method for the pets to call when their internal state/age changes to set isAgeValid to false. Having it marked public (or more appropriately at the design-level, package) works out okay, because calling it at an inappropriate time does not damage any data, it just causes extra calculations down the line.
JoshJordan
I would really like to have classes A and B properly separated. That's why I thought about putting the update code in a separate class in the first place.
Smasher
Proper separation would probably be the answer above, where there is a subclass of a generic collection typed to Pet, that adds this functionality.
JoshJordan