Самая слабая связь была бы, если бы компоненты не знали о своих менеджерах. Вот пример того, как это будет работать. Обратите внимание, что этот подход требует своего рода фабричного механизма, если все компоненты должны быть добавлены в менеджер. (Nat Pryce - "Если существует связь между двумя объектами, какой-то другой объект должен установить связь." )
abstract class BaseComponent
{
public event EventHandler SomethingHappened;
}
abstract class BaseManager<TComponent> where TComponent : BaseComponent
{
List<TComponent> components = new List<TComponent>();
public virtual void AddComponent(TComponent component)
{
components.Add(component);
component.SomethingHappened += (s, e) => OnSomethingHappened(component);
}
public abstract void OnSomethingHappened(TComponent component);
}
Если компоненты не могут быть независимыми от своих менеджеров, я думаю, было бы лучше, если бы они зависели от интерфейса, определяемого потребностями компонента. Это принцип разделения интерфейсов
interface IManager
{
void ManageMe(BaseComponent component);
}
abstract class BaseComponent
{
public BaseComponent(IManager manager)
{
manager.ManageMe(this);
}
}
abstract class BaseManager<TComponent> : IManager where TComponent : BaseComponent
{
void IManager.ManageMe(BaseComponent component)
{
ManageMe((TComponent)component);
}
protected abstract void ManageMe(TComponent component);
}
interface IPhysicsManager : IManager
{
void AnotherCallback(PhysicsComponent comp);
}
abstract class PhysicsComponent : BaseComponent
{
public PhysicsComponent(IPhysicsManager manager)
: base(manager)
{
manager.AnotherCallback(this);
}
}
abstract class PhysicsManager : BaseManager<PhysicsComponent>, IPhysicsManager
{
protected override void ManageMe(PhysicsComponent component)
{
throw new NotImplementedException();
}
public void AnotherCallback(PhysicsComponent comp)
{
throw new NotImplementedException();
}
}
Недостатком является то, что система типов не обеспечивает передачу правильного менеджера, и приведение в BaseManager может завершиться ошибкой. Я бы все-таки предпочел этот способ и «сохранить запах в моей инфраструктуре», а не иметь круглые шаблоны, загрязняющие все мои конкретные компоненты и менеджеров.