Ось загальний сценарій, який завжди мені страждає.
У мене є об'єктна модель з батьківським об'єктом. Батько містить деякі дочірні об’єкти. Щось на зразок цього.
public class Zoo
{
public List<Animal> Animals { get; set; }
public bool IsDirty { get; set; }
}
Кожен дочірній об’єкт має різні дані та методи
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public void MakeMess()
{
...
}
}
Коли дитина змінюється, у цьому випадку, коли викликається метод MakeMess, деяке значення в батьківській програмі потрібно оновити. Скажімо, коли певний поріг Animal's заплутався, тоді потрібно встановити прапор IsDirty в зоопарку.
Є кілька способів впоратися з цим сценарієм (який я знаю).
1) Кожна тварина може мати посилання на батьківський зоопарк, щоб повідомляти про зміни.
public class Animal
{
public Zoo Parent { get; set; }
...
public void MakeMess()
{
Parent.OnAnimalMadeMess();
}
}
Це здається найгіршим варіантом, оскільки він з'єднує Тварину з його батьківським об'єктом. Що робити, якщо я хочу тварину, яка живе в будинку?
2) Ще одним варіантом, якщо ви використовуєте мову, яка підтримує події (наприклад, C #), - це змусити батьків підписатися на зміну подій.
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)
{
...
}
}
Це, здається, працює, але з досвіду важко підтримувати. Якщо тварини коли-небудь змінюють зоопарк, вам доведеться скасувати передплату на старий зоопарк та повторно підписатися на новий зоопарк. Це тільки погіршується, коли дерево композиції стає глибшим.
3) Інший варіант - перемістити логіку до батьківської.
public class Zoo
{
public void AnimalMakesMess(Animal animal)
{
...
}
}
Це здається дуже неприродним і викликає дублювання логіки. Наприклад, якщо у мене був об'єкт House, який не ділиться жодним спільним батьківським спадком із Zoo ..
public class House
{
// Now I have to duplicate this logic
public void AnimalMakesMess(Animal animal)
{
...
}
}
Я ще не знайшов гарної стратегії вирішення цих ситуацій. Що ще є? Як це можна спростити?