Aquí hay un escenario común que siempre es frustrante para mí enfrentar.
Tengo un modelo de objeto con un objeto padre. El padre contiene algunos objetos secundarios. Algo como esto.
public class Zoo
{
public List<Animal> Animals { get; set; }
public bool IsDirty { get; set; }
}
Cada objeto secundario tiene varios datos y métodos.
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public void MakeMess()
{
...
}
}
Cuando el elemento secundario cambia, en este caso cuando se llama al método MakeMess, es necesario actualizar algún valor en el elemento primario. Digamos que cuando un cierto umbral de Animal ha hecho un desastre, entonces se debe establecer la bandera IsDirty del zoológico.
Hay algunas maneras de manejar este escenario (que yo sepa).
1) Cada animal puede tener una referencia primaria del zoológico para comunicar los cambios.
public class Animal
{
public Zoo Parent { get; set; }
...
public void MakeMess()
{
Parent.OnAnimalMadeMess();
}
}
Esta se siente como la peor opción, ya que combina Animal con su objeto padre. ¿Qué pasa si quiero un animal que vive en una casa?
2) Otra opción, si está utilizando un lenguaje que admite eventos (como C #) es hacer que el padre se suscriba para cambiar los 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)
{
...
}
}
Esto parece funcionar, pero por experiencia se hace difícil de mantener. Si los animales alguna vez cambian los zoológicos, debe cancelar la suscripción a eventos en el antiguo zoológico y volver a suscribirse en el nuevo zoológico. Esto solo empeora a medida que el árbol de composición se vuelve más profundo.
3) La otra opción es mover la lógica al padre.
public class Zoo
{
public void AnimalMakesMess(Animal animal)
{
...
}
}
Esto parece muy poco natural y provoca la duplicación de la lógica. Por ejemplo, si tuviera un objeto House que no comparte ningún padre de herencia común con Zoo ...
public class House
{
// Now I have to duplicate this logic
public void AnimalMakesMess(Animal animal)
{
...
}
}
Todavía no he encontrado una buena estrategia para hacer frente a estas situaciones. ¿Qué más hay disponible? ¿Cómo se puede simplificar esto?