消息系统的作用:
在游戏开发中,观察者模式是一种非常常见的设计模式。观察者模式有效的避免了不同系统之间的耦合。通过观察者模式,A系统不必关注B系统内部的实现的迭代,只需关注B系统广播出去的消息即可,大大提高了开发效率和稳定性。
代码设计:
设计思路:
消息系统,顾名思义,需要有广播的地方,也需要有接收的地方。所以可以利用委托去管理不同系统的消息。对于发送方,需要提供广播的方法,即消息发送。对于接收方,需要提供消息订阅的方法,即注册消息。这样一来当一条消息广播时,所有订阅了次消息的模块都会收到次消息。并且,还需要提供取消订阅的方法,毕竟需不需要此消息是接收方决定的。
与此同时,不同消息在广播的时候或许会携带自身数据,接收方需要利用这些数据进行后续的处理。但是不同消息携带的数据类型或者结构大不相同,因此需要利用泛型结构去适配各种各样的数据类型或者结构。
最后,不同消息用枚举来区分。订阅同一个消息的委托(回调函数)都存储在统一结构中。
设计模式:
消息系统,单例模式,唯一实例,唯一控制。
数据结构:
使用字典去存储同一消息的委托(回调函数)。特别注意的是由于字典不支持泛型类型,所以需要通过定义对应的接口类。
导图:
关键代码:
MessageData.cs
用来存储注册到消息系统的回调函数,本质就是个委托。因为字典不支持泛型,因此需要提供接口类。
public interface IMessageData
{
}
public class MessageData <T> : IMessageData
{
public UnityAction<T> MessageEvents;
public MessageData(UnityAction<T> action)
{
MessageEvents += action;
}
}
MessageManager.cs
统一管理各个系统的消息,包括消息注册和反注册,消息广播。核心就是新建委托,回调函数添加至委托,调用委托。
public class MessageManager
{
private static MessageManager _instance;
public static MessageManager Instance
{
get
{
if (_instance == null)
{
_instance = new MessageManager();
}
return _instance;
}
}
private Dictionary<MessageEvent, IMessageData> _dictionaryMessage;
private MessageManager()
{
_dictionaryMessage = new Dictionary<MessageEvent, IMessageData>();
}
public void Register<T>(MessageEvent key, UnityAction<T> action)
{
if (_dictionaryMessage.TryGetValue(key, out var previousAction))
{
if (previousAction is MessageData<T> messageData)
{
messageData.MessageEvents += action;
}
}
else
{
MessageData<T> messageData = new MessageData<T>(action);
_dictionaryMessage.Add(key, messageData);
}
}
public void UnRegister<T>(MessageEvent key, UnityAction<T> action)
{
if (_dictionaryMessage.TryGetValue(key, out var previousAction))
{
if (previousAction is MessageData<T> MessageData)
{
MessageData.MessageEvents -= action;
}
}
}
public void Send<T>(MessageEvent key, T data)
{
if (_dictionaryMessage.TryGetValue(key, out var previousAction))
{
//(previousAction as MessageData<T>)?.MessageEvents.Invoke(data);
if (previousAction is MessageData<T> MessageData)
{
MessageData.MessageEvents(data);
}
}
}
public void Clear()
{
_dictionaryMessage.Clear();
}
}