Aqui está um cenário comum que é sempre frustrante para mim.
Eu tenho um modelo de objeto com um objeto pai. O pai contém alguns objetos filhos. Algo assim.
public class Zoo
{
public List<Animal> Animals { get; set; }
public bool IsDirty { get; set; }
}
Cada objeto filho possui vários dados e métodos
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public void MakeMess()
{
...
}
}
Quando o filho muda, nesse caso, quando o método MakeMess é chamado, algum valor no pai precisa ser atualizado. Digamos que quando um certo limite de Animal fez uma bagunça, o sinalizador IsDirty do Zoo precisa ser definido.
Existem algumas maneiras de lidar com esse cenário (que eu saiba).
1) Cada animal pode ter uma referência de zoológico principal para comunicar as alterações.
public class Animal
{
public Zoo Parent { get; set; }
...
public void MakeMess()
{
Parent.OnAnimalMadeMess();
}
}
Essa é a pior opção, pois une Animal ao objeto pai. E se eu quiser um animal que mora em uma casa?
2) Outra opção, se você estiver usando um idioma que suporta eventos (como C #), é pedir que o pai se inscreva para alterar os eventos.
public class Animal
{
public event OnMakeMessDelegate OnMakeMess;
public void MakeMess()
{
OnMakeMess();
}
}
public class Zoo
{
...
public void SubscribeToChanges()
{
foreach (var animal in Animals)
{
animal.OnMakeMess += new OnMakeMessDelegate(OnMakeMessHandler);
}
}
public void OnMakeMessHandler(object sender, EventArgs e)
{
...
}
}
Isso parece funcionar, mas por experiência fica difícil de manter. Se os animais mudarem de zoológico, você precisará cancelar a inscrição de eventos no zoológico antigo e se inscrever novamente no novo zoológico. Isso só piora à medida que a árvore de composição fica mais profunda.
3) A outra opção é mover a lógica para o pai.
public class Zoo
{
public void AnimalMakesMess(Animal animal)
{
...
}
}
Isso parece muito antinatural e causa duplicação de lógica. Por exemplo, se eu tivesse um objeto House que não compartilhe nenhum pai de herança comum com o Zoo.
public class House
{
// Now I have to duplicate this logic
public void AnimalMakesMess(Animal animal)
{
...
}
}
Ainda não encontrei uma boa estratégia para lidar com essas situações. O que mais está disponível? Como isso pode ser simplificado?