[Unity 程式碼寫法整理]訊息機制(三)
實現第二種即時的訊息機制,寫法的話跟第一種幾乎一樣,只是去掉了Queue並且在訊息發出時執行Handler
==============================
1.訊息體 AbstractMessage:
public abstract class AbstractMessage
{
public string messageName;
}
同第一種
==============================
2.訊息處理函式Handler:
Action<AbstractMessage> handler
同第一種
==============================
3.訊息中心MessageCenter在第一種的基礎上做一些修改
public class MessageCenter : MonoSingleton<MessageCenter>
{
private Dictionary<string,Action<AbstractMessage>> messageDic = new Dictionary<string,Action<AbstratMessage>>();
//HandleMessage 處理髮送的訊息
private void HandleMessage(AbstractMessage message)
{
string messageName = message.messageName;
if(messageDic.ContainsKey(messageName))
{
messageDic[messageName](message);
return;
}
Debug.LogError("This message has not registed : " + message.messageName);
}
//RegistMessage 註冊訊息
public void RegistMessage(string messageName,Action<AbstractMessage> handler)
{
if(messageDic.ContainsKey(messageName))
{
messageDic[messageName] += handler;
return;
}
messageDic[messageName] = handler;
}
//UnRegistMessage 登出訊息
public void UnRegistMessage(string messageName,Action<AbstractMessage> handler)
{
if(messageDic.ContainsKey(messageName))
{
if(messageDic[messageName].GetInvocationList().Length > 1)
{
messageDic[messageName] -= handler;
return;
}
messageDic.Remove(messageName);
return;
}
Debug.LogError("This Message Not Registed : " + messageName);
}
//DispatchMessage 發訊息
public void DispatchMessage(AbstractMessage message)
{
HandleMessage(message);
}
}
相當於是第一種訊息中心的簡化,MessageQueue理論上來說,並不需要單例類繼承Monobehaviour了,因為不需要Update去實現Loop檢測訊息功能。但是考慮到可以將兩種訊息機制合二為一,所以還是繼承MonoSingleton。
==============================
4.在對訊息機制的實際運用中,只有三種方法需要運用到,也就是MessageCenter裡的註冊、登出、傳送訊息。而兩種訊息機制除了傳送訊息,其他並沒有區別,也就是說,可以給傳送訊息再新增一個引數,以區分這兩種訊息種類,我比較偏向於使用列舉來實現。
public enum DispatchMessageType
{
Immediate, //傳送即時訊息
Queued //傳送佇列訊息
}
public class MessageCenter : MonoSingleton<MessageCenter>
{
private Dictionary<string,Action<AbstractMessage>> messageDic = new Dictionary<string,Action<AbstratMessage>>();
private Queue<AbstractMessage> messageQueue = new Queue<AbstractMessage>();
//Call per frame
private void Update()
{
while(messageQueue.Peek() != null)
{
AbstractMessage message = messageQueue.Dequeue();
HandleMessage(message);
}
}
//HandleMessage 處理髮送的訊息
private void HandleMessage(AbstractMessage message)
{
string messageName = message.messageName;
if(messageDic.ContainsKey(messageName))
{
messageDic[messageName](message);
return;
}
Debug.LogError("This message has not registed : " + message.messageName);
}
//RegistMessage 註冊訊息
public void RegistMessage(string messageName,Action<AbstractMessage> handler)
{
if(messageDic.ContainsKey(messageName))
{
messageDic[messageName] += handler;
return;
}
messageDic[messageName] = handler;
}
//UnRegistMessage 登出訊息
public void UnRegistMessage(string messageName,Action<AbstractMessage> handler)
{
if(messageDic.ContainsKey(messageName))
{
if(messageDic[messageName].GetInvocationList().Length > 1)
{
messageDic[messageName] -= handler;
return;
}
messageDic.Remove(messageName);
return;
}
Debug.LogError("This Message Not Registed : " + messageName);
}
//DispatchMessage 發訊息
public void DispatchMessage(AbstractMessage message,DispatchMessageType typeEnum)
{
switch(typeEnum)
{
case DispatchMessageType.Immediate:
HandleMessage(message);
break;
case DispatchMessageType.Queued:
messageQueue.Enqueue(message);
break;
default:break;
}
}
}
這樣就將即時訊息和佇列訊息合二為一,組成了一個完整的訊息中心。
==============================
5.最後補充一下,因為現在所使用的Handler都是委託型別,如果將其改為介面,則可以在一個類中實現介面中的函式配合switch以達成統一處理訊息的目的。比如定義一個介面IMessageHandler。
public interface IMessageHandler
{
void OnReceiveMessage(AbstractMessage message);
}
然後將MessageCenter裡面所有的Action<AbstractMessage>全部替換為IMessageHandler(懶得上程式碼)
這樣的話,假如一個類需要接收訊息,繼承此介面即可
public class Test : Monobehaviour,IHandleMessage
{
public void OnReceiveMessage(AbstractMessage message)
{
switch(message.messageName)
{
case "message1":
//do something
break;
//case ...
}
}
}
或者再封裝一層Monobehaviour,提供註冊和登出函式。
public abstract MessageMonobehaviour : MonoBehaviour,IHandler
{
protected virtual void RegistMessage(string MessageName)
{
//由於委託替換為介面,直接用this即可
MessageCenter.Instance.RegistMessage(MessageName,this);
}
protected virtual void UnRegistMessage(string MessageName)
{
//由於委託替換為介面,直接用this即可
MessageCenter.Instance.UnRegistMessage(MessageName,this);
}
//子類重寫此方法以處理訊息
public virtual void OnReceiveMessage(AbstractMessage message)
{
Debug.Log(this.GetType() + " ReceiveMessage, MessageName : " + message.messageName);
}
}
==============================
沒了,訊息機制應該就這麼多,想到了再補充
相關文章
- OC訊息機制,訊息轉發機制
- 訊息機制
- 深入淺出 Runtime(三):訊息機制
- iOS訊息機制iOS
- SAP訊息機制
- Android訊息機制原始碼分析Android原始碼
- Android程式間通訊–訊息機制及IPC機制實現薦Android
- 全面剖析Android訊息機制原始碼Android原始碼
- 訊息機制篇——初識訊息與訊息佇列佇列
- JMS java 訊息機制Java
- Windows訊息機制概述Windows
- Android訊息機制Message訊息池Android
- RabbitMQ訊息佇列(三):任務分發機制MQ佇列
- 原始碼分析:Android訊息處理機制原始碼Android
- Handler訊息處理機制原始碼解析 上原始碼
- Android Handler訊息機制原始碼解讀Android原始碼
- Rabbitmq可靠訊息投遞,訊息確認機制MQ
- Android訊息傳遞之Handler訊息機制Android
- Android應用程式訊息處理機制Android
- Windows應用程式的訊息處理機制Windows
- flutter 訊息傳遞機制Flutter
- android訊息機制—HandlerAndroid
- RabbitMQ 訊息確認機制MQ
- 理解 Android 訊息機制Android
- 重拾 ObjC 訊息機制OBJ
- 簡析Windows訊息機制Windows
- Kafka 訊息儲存機制Kafka
- Android訊息機制HandlerAndroid
- Android 之訊息機制Android
- Handler訊息傳遞機制
- Android的訊息機制Android
- WebRTC中的訊息機制Web
- WTL的訊息機制 (轉)
- 編寫高質量OC程式碼52建議總結:12.理解訊息轉發機制C程式
- 詳解 Handler 訊息處理機制(附自整理超全 Q&A)
- Android非同步訊息機制Android非同步
- Android訊息機制Handler用法Android
- 【RocketMQ】訊息的刷盤機制MQ