I believe that combining the Observer pattern (publish/subscribe logic) along side with the Mediator one can be a good solution to your problem. Your Mediator class will act as an Event Manager (most of your classes will depend on it as a mediator rather than depending on each others) :
public class MessageManager{
private Dictionary<string,List<MessageListener>> listeners;
public void sendMessage(Message m){
//loop over listeners of m
}
public void addMessageListener(MessageListener ml){
//add a listener
}
public void removeMessageListener(MessageListener ml){
//remove a listener
}
}
Message
would be the parent interface, having a generic abstraction at this level is very important as it avoids the MessageManager
from distinguishing between your 50-60 types of messages and thus becoming a nightmare to maintain. The specificity of depending on a particular sub-type of Message
should be moved to a lower level: the direct consumers.