Ecco uno scenario comune che è sempre frustrante per me da affrontare.
Ho un modello a oggetti con un oggetto genitore. Il genitore contiene alcuni oggetti figli. Qualcosa di simile.
public class Zoo
{
public List<Animal> Animals { get; set; }
public bool IsDirty { get; set; }
}
Ogni oggetto figlio ha vari dati e metodi
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public void MakeMess()
{
...
}
}
Quando il bambino cambia, in questo caso quando viene chiamato il metodo MakeMess, è necessario aggiornare un valore nel genitore. Diciamo che quando una certa soglia di Animal ha fatto un casino, allora il flag IsDirty dello Zoo deve essere impostato.
Ci sono alcuni modi per gestire questo scenario (che io sappia).
1) Ogni animale può avere un riferimento Zoo per poter comunicare le modifiche.
public class Animal
{
public Zoo Parent { get; set; }
...
public void MakeMess()
{
Parent.OnAnimalMadeMess();
}
}
Questa sembra l'opzione peggiore dal momento che associa Animal al suo oggetto genitore. Cosa succede se voglio un animale che vive in una casa?
2) Un'altra opzione, se stai utilizzando una lingua che supporta eventi (come C #), è che il genitore si iscriva per cambiare gli eventi.
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)
{
...
}
}
Questo sembra funzionare ma dall'esperienza diventa difficile da mantenere. Se gli animali cambiano mai Zoo, devi annullare l'iscrizione agli eventi nel vecchio zoo e iscriversi nuovamente al nuovo zoo. Questo peggiora solo quando l'albero di composizione diventa più profondo.
3) L'altra opzione è spostare la logica su padre.
public class Zoo
{
public void AnimalMakesMess(Animal animal)
{
...
}
}
Questo sembra molto innaturale e causa la duplicazione della logica. Ad esempio, se avessi un oggetto House che non condivide alcun genitore ereditario comune con Zoo ..
public class House
{
// Now I have to duplicate this logic
public void AnimalMakesMess(Animal animal)
{
...
}
}
Non ho ancora trovato una buona strategia per affrontare queste situazioni. Cos'altro è disponibile? Come può essere reso più semplice?