您的位置:首页 > 其它

SRPG游戏开发(十八)第六章 基本框架 - 三 消息事件系统(Message Center)

2018-03-16 12:15 471 查看
返回目录

第六章 基本框架(Framework)

三 消息事件系统(Message Center)

常见的消息事件系统,无外乎注册,注销和执行三个方法。基本都是大同小异。

这里也是相同的,只是把参数分离成单独一个类。

下面介绍几种常见方式,各有利弊,你可以使用1种或几种混用。

namespace DR.Book.SRPG_Dev.Framework
{
/// <summary>
/// 消息中心。
/// 消息中心的方式比较多,你可以挑选一种或几种。
/// 这里把所有东西都放在了MessageCenter中,
/// </summary>
public static class MessageCenter
{
// TODO 参数,注册,注销

/// <summary>
/// 分发Message的实现
/// </summary>
/// <param name="message"></param>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <param name="messageParams"></param>
private static void ExecuteMessage(string message, object sender, MessageArgs args, params object[] messageParams)
{
if (string.IsNullOrEmpty(message))
{
Debug.LogError("[MessageCenter] Argument named 'message' is null or empty.");
return;
}

if (sender == null)
{
Debug.LogError("[MessageCenter] Argument named 'sender' is null");
return;
}

// TODO 分发并执行消息事件
}
}
}


1 事件参数(MessageArgs.cs)

参数可以使用
object[]
类型,这里单独建出来一个类。

这里只是参数,你也可以将事件名称(name)和发送者(sender)等也放入其中。

还是按需来。

using System;

namespace DR.Book.SRPG_Dev.Framework
{
public abstract class MessageArgs : EventArgs, IDisposable
{
public void Dispose()
{
OnDispose();
}

protected virtual void OnDispose()
{

}
}
}


2 监听方式(Delegate)

使用监听的方式,常见的是委托模式。这里也是使用委托。

/// <summary>
/// Delegate Listener
/// </summary>
/// <param name="message"></param>
/// <param name="sender"></param>
/// <param name="messageArgs"></param>
/// <param name="messageParams"></param>
public delegate void MessageListener(string message, object sender, MessageArgs messageArgs, params object[] messageParams);

/// <summary>
/// 注册的Listener.
/// 你也可以不使用List,直接使用MessageListener.
/// 注册的时候用 listener += method.
/// 注销的时候用 listener -= method.
/// </summary>
private static readonly Dictionary<string, List<MessageListener>> s_ListenerDict = new Dictionary<string, List<MessageListener>>();


就像注释中写的一样,你可以使用委托的
+=
-=
,也可以使用
List
Add
Remove
来控制监听。

2.1 注册与注销(Add/Remove Listener)

注册其实就是添加监听者(Add Listener),代码如下。

/// <summary>
/// 注册Listener
/// </summary>
/// <param name="message"></param>
/// <param name="listener"></param>
public static void AddListener(string message, MessageListener listener)
{
if (string.IsNullOrEmpty(message))
{
Debug.LogError("[MessageCenter] Argument named 'message' is null or empty.");
return;
}

if (listener == null)
{
Debug.LogError("[MessageCenter] Argument named 'listener' is null.");
return;
}

List<MessageListener> listeners;
if (!s_ListenerDict.TryGetValue(message, out listeners))
{
listeners = new List<MessageListener>();
s_ListenerDict.Add(message, listeners);
}

if (!listeners.Contains(listener))
{
listeners.Add(listener);
}
}


注销同样的,就是删除监听者(Remove Listener),代码如下。

/// <summary>
/// 注销Listener
/// 如果Listener是MonoBehaviour, 你可以在OnDestroy或其它销毁Method中,加入注销.
/// </summary>
/// <param name="message"></param>
/// <param name="listener"></param>
public static void RemoveListener(string message, MessageListener listener)
{
if (string.IsNullOrEmpty(message))
{
Debug.LogError("[MessageCenter] Argument named 'message' is null or empty.");
return;
}

104c3
if (listener == null)
{
Debug.LogError("[MessageCenter] Argument named 'listener' is null.");
return;
}

List<MessageListener> listeners;
if (!s_ListenerDict.TryGetValue(message, out listeners))
{
return;
}

if (listeners.Remove(listener) && listeners.Count == 0)
{
s_ListenerDict.Remove(message);
}
}

/// <summary>
/// 注销Listeners
/// </summary>
/// <param name="message"></param>
public static void RemoveListeners(string message)
{
if (string.IsNullOrEmpty(message))
{
Debug.LogError("[MessageCenter] Argument named 'message' is null or empty.");
return;
}

s_ListenerDict.Remove(message);
}


2.2 执行事件(Trigger Event)

执行消息事件,也就是执行监听者。

ExecuteMessage
方法中添加。

// 分发给Listener
List<MessageListener> listeners;
if (s_ListenerDict.TryGetValue(message, out listeners))
{
for (int i = 0; i < listeners.Count; i++)
{
MessageListener listener = listeners[i];
if (listener != null)
{
listener(message, sender, args, messageParams);
}
}
}


3 处理者方式(Handler)

使用处理者的方式,要确定哪些是处理者,你可以建立一个基类,然后处理者全部继承自它。

但那不是一种好的方法。一般来说都是继承接口来实现。

3.1 处理者接口(IMessageHandler.cs)

处理者接口,只需要一个处理事件的方法。这和Listener是一样的。

namespace DR.Book.SRPG_Dev.Framework
{
public interface IMessageHandler
{
void ExecuteMessage(string message, object sender, MessageArgs messageArgs, params object[] messageParams);
}
}


只要继承了这个接口的类,全部都会变成处理者。

3.2 注册与注销(Register/Unregister Handler)

首先,和Listener一样,你需要一个容器保存处理者。

/// <summary>
/// 注册的Handler.
/// 你也可以使用Dictionary<string, List<IMesageHandler>>来分类保存。
/// </summary>
private static readonly List<IMessageHandler> s_Handlers = new List<IMessageHandler>();


其次,你需要注册。

/// <summary>
/// 注册Handler
/// </summary>
/// <param name="handler"></param>
public static void RegisterHandler(IMessageHandler handler)
{
if (handler == null)
{
Debug.LogError("[MessageCenter] Argument named 'handler' is null.");
return;
}

if (!s_Handlers.Contains(handler))
{
s_Handlers.Add(handler);
}
}


最后,依然是注销。

/// <summary>
/// 注销Handler.
/// 如果Handler是MonoBehaviour, 你可以在OnDestroy或其它销毁Method中,加入注销.
/// </summary>
/// <param name="handler"></param>
public static void UnregisterHandler(IMessageHandler handler)
{
if (handler == null)
{
Debug.LogError("[MessageCenter] Argument named 'handler' is null.");
return;
}

s_Handlers.Remove(handler);
}


3.3 执行事件(Trigger Event)

使用处理者执行事件,在
ExecuteMessage
方法中添加。

// 分发给Handler
if (s_Handlers.Count > 0)
{
for (int i = 0; i < s_Handlers.Count; i++)
{
IMessageHandler handler = s_Handlers[i];
if (handler == null)
{
s_Handlers.RemoveAt(i);
i--;
}
else
{
handler.ExecuteMessage(message, sender, args, messageParams);
}
}
}


如果
handler
是一个
MonoBehaviour
,并且在销毁它时,你忘记注销了。那么这种写法可以自动注销它。

4 控制器方式(Controller)

控制器方式常见于MVC框架中。

你可以选择常规控制器,也可以选择Unity中的ScriptableObject方式。

4.1 控制器基类(ControllerBase.cs)

常规控制器如下。

如果你要使用ScriptableObject方式,只需继承
ScriptableObject
,其它并没有不同。

namespace DR.Book.SRPG_Dev.Framework
{
public abstract class MessageControllerBase
{
public abstract void ExecuteMessage(string message, object sender, MessageArgs messageArgs, params object[] messageParams);
}
}


4.2 注册与注销(Register/Unregsiter Controller)

首先,同样的,你需要一个容器保存控制器。

如果是动态创建,则保存
Type


如果是使用创建好的
ScriptableObject
,则使用
Dictionary<string, MessageControllerBase>


/// <summary>
/// 注册的Controller.
/// 这里使用普通的类,并使用System.Activator.CreateInstance(System.Type type)创建,并执行.
/// 你也可以不用它,而使用Asset的ScriptableObject,见方法ExecuteMessage中的注释,
/// 如果是动态创建的ScriptableObject,且你需要销毁它,则要使用Destroy,不要不管或赋值null。
/// </summary>
private static readonly Dictionary<string, Type> s_ControllerDict = new Dictionary<string, Type>();


其次,注册也是添加进容器。

如果是使用创建好的
ScriptableObject
,则在这个方法中,使用
ScriptableObject.CreateInstance()
创建。

/// <summary>
/// 注册Controller
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="message"></param>
public static void RegisterController<T>(string message) where T : MessageControllerBase
{
if (string.IsNullOrEmpty(message))
{
Debug.LogError("[MessageCenter] Argument named 'message' is null or empty.");
return;
}

Type type = typeof(T);
if (type.IsAbstract)
{
Debug.LogError("[MessageCenter] Type of controller is abstract.");
return;
}

if (s_ControllerDict.ContainsKey(message))
{
Debug.LogError("[MessageCenter] Type of controller is exist.");
return;
}

s_ControllerDict.Add(message, type);
}


最后,是注销。

如果是使用创建好的
ScriptableObject
,则在这个方法中,使用
ScriptableObject.Destroy()
销毁。

/// <summary>
/// 注销Controller
/// </summary>
/// <param name="message"></param>
public static void UnregisterController(string message)
{
if (string.IsNullOrEmpty(message))
{
Debug.LogError("[MessageCenter] Argument named 'message' is null or empty.");
return;
}

s_ControllerDict.Remove(message);
}


4.3 执行事件(Trigger Event)

使用控制器执行事件,在
ExecuteMessage
方法中添加。

// 分发给Controller
Type type;
if (s_ControllerDict.TryGetValue(message, out type))
{
MessageControllerBase controller = Activator.CreateInstance(type) as MessageControllerBase;
if (controller != null)
{
controller.ExecuteMessage(message, sender, args, messageParams);
}
}

/*
///// 使用已经创建好的ScriptableObject,Dictionary<string, MessageControllerBase> s_ControllerDict;
// MessageControllerBase controller;
// if (s_ControllerDict.TryGetValue(message, out controller))
// {
//     controller.ExecuteMessage(message, sender, args, messageParams);
// }
*/

/*
///// 使用动态创建的ScriptableObject
// Type assetType;
// if (s_ControllerDict.TryGetValue(message, out assetType))
// {
//     MessageControllerBase controller = ScriptableObject.CreateInstance(assetType) as MessageControllerBase;
//     controller.ExecuteMessage(message, sender, args, messageParams);
//     ScriptableObject.Destroy(controller);
// }
*/


5 发送事件(Send)

发送事件就只是一个外部接口。

/// <summary>
/// 分发Message
/// </summary>
/// <param name="message"></param>
/// <param name="sender"></param>
/// <param name="messageParams"></param>
public static void Send(string message, object sender, params object[] messageParams)
{
ExecuteMessage(message, sender, null, messageParams);
}

/// <summary>
/// 分发Message
/// </summary>
/// <param name="message"></param>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <param name="messageParams"></param>
public static void Send(string message, object sender, MessageArgs args, params object[] messageParams)
{
ExecuteMessage(message, sender, args, messageParams);
}


6 类型扩展(Type Extension)

这里类型扩展,只是让
MonoBehaviour
可以发送事件。

/// <summary>
/// 让MonoBehaviour可以发送消息
/// </summary>
/// <param name="mono"></param>
/// <param name="message"></param>
/// <param name="messageParams"></param>
public static void SendByMessageCenter(this MonoBehaviour mono, string message, params object[] messageParams)
{
if (mono == null)
{
Debug.LogError("[MessageCenter] Type extention. Argument named 'mono' is null.");
return;
}

ExecuteMessage(message, mono, null, messageParams);
}

/// <summary>
/// 让MonoBehaviour可以发送消息
/// </summary>
/// <param name="mono"></param>
/// <param name="message"></param>
/// <param name="args"></param>
/// <param name="messageParams"></param>
public static void SendByMessageCenter(this MonoBehaviour mono, string message, MessageArgs args, params object[] messageParams)
{
if (mono == null)
{
Debug.LogError("[MessageCenter] Type extention. Argument named 'mono' is null.");
return;
}

ExecuteMessage(message, mono, args, messageParams);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐