Вариант первый — минимальная защита от индуса:
class Event {
public void subscribe(...) {}
}
class OwnedEvent extends Event {
public void fire(...) {}
public void addReaction(...) {}
}
Владелец события создает объект класса OwnedEvent, но перед передачей его другим объектам приводит к Event. При попытке приведения события обратно — больно бить по рукам.
Вариант второй — максимальная защита от индуса, но с повышенным расходом памяти.
class Event {
public void subscribe(...) {}
public static class Owner {
private final Event event = new Event();
public void fire(...) {}
public void addReaction(...) {}
public Event getEvent() { return event; }
}
}
Смысл в том, что при таком подходе класс Event.Owner должен иметь доступ к приватным полям класса Event, чем и можно воспользоваться.
PS на Java не писал ничего уже 4 года, могу накосячить с синтаксисом. Надеюсь, это не помешает пониманию написанного.