Oto typowy scenariusz, który zawsze frustruje mnie.
Mam model obiektu z obiektem nadrzędnym. Element nadrzędny zawiera niektóre obiekty podrzędne. Coś takiego.
public class Zoo
{
public List<Animal> Animals { get; set; }
public bool IsDirty { get; set; }
}
Każdy obiekt podrzędny ma różne dane i metody
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public void MakeMess()
{
...
}
}
Kiedy dziecko zmienia się, w tym przypadku, gdy wywoływana jest metoda MakeMess, pewna wartość w obiekcie nadrzędnym musi zostać zaktualizowana. Powiedzmy, że kiedy pewien próg Animalów popełnił bałagan, należy ustawić flagę Zoo IsDirty.
Istnieje kilka sposobów radzenia sobie z tym scenariuszem (o których wiem).
1) Każde zwierzę może mieć nadrzędny numer referencyjny Zoo w celu komunikowania zmian.
public class Animal
{
public Zoo Parent { get; set; }
...
public void MakeMess()
{
Parent.OnAnimalMadeMess();
}
}
To wydaje się najgorszą opcją, ponieważ łączy Animal z obiektem nadrzędnym. Co jeśli chcę zwierzęcia mieszkającego w domu?
2) Inną opcją, jeśli używasz języka obsługującego zdarzenia (takiego jak C #), jest to, aby rodzic subskrybował zmiany zdarzeń.
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)
{
...
}
}
To wydaje się działać, ale z doświadczenia staje się trudne do utrzymania. Jeśli zwierzęta kiedykolwiek zmienią zoo, musisz anulować subskrypcję wydarzeń w starym zoo i ponownie zapisać się w nowym zoo. To tylko pogarsza się, gdy drzewo kompozycji pogłębia się.
3) Inną opcją jest przeniesienie logiki do rodzica.
public class Zoo
{
public void AnimalMakesMess(Animal animal)
{
...
}
}
Wydaje się to bardzo nienaturalne i powoduje duplikację logiki. Na przykład, gdybym miał obiekt House, który nie ma wspólnego wspólnego obiektu nadrzędnego z Zoo ..
public class House
{
// Now I have to duplicate this logic
public void AnimalMakesMess(Animal animal)
{
...
}
}
Nie znalazłem jeszcze dobrej strategii radzenia sobie z tymi sytuacjami. Co jeszcze jest dostępne? Jak można to uprościć?