消息模式有三個主要對象,分別是:
- 消息監聽者:監聽消息
- 消息中心:存儲、刪除消息
- 消息發送者:發送廣播
看下面的圖,大概對每個部分的職能能夠清楚的瞭解:
下面是主要代碼:
Msg.lua
相當於消息中心,對所有消息進行處理
其中Remove的三個參數支持多種方式的移除消息方式,具體的可以參考代碼邏輯進行理解和修改
Msg = {}
Msg.init = function()
--[[
msgmap = {
msgId = {
{instance1, func1},
{instance2, func2}
}
}
]]
Msg.msgmap = {}
end
--@desc 添加綁定事件
--@arg ... msgId, instance, func
--@arg msgId 消息Id
--@arg func 消息執行函數
Msg.Add = function(instance, msgId, func)
local msgObj = {instance, func}
if not Msg.msgmap[msgId] then
Msg.msgmap[msgId] = {msgObj}
else
local list = Msg.msgmap[msgId]
for _, obj in pairs(list) do
if obj[1] == instance and obj[2] == func then
return
end
end
table.insert(Msg.msgmap[msgId], msgObj)
end
end
--@desc 移除綁定事件
--@arg msgId 消息Id
--@arg instance 監聽實例
--@arg func 消息執行函數
Msg.Remove = function(msgId, instance, func)
if msgId then
if not instance and not func then
Msg.msgmap[msgId] = nil
else
local list = Msg.msgmap[msgId]
Msg._remove(list, instance, func)
end
else
for id, list in pairs(Msg.msgmap) do
Msg._remove(list, instance, func)
end
end
end
Msg._remove = function(list, instance, func)
if not list then
return
end
for index, msgObj in pairs(list) do
if instance and func then
if msgObj[1] == instance and msgObj[2] == func then
table.remove(list, index)
end
elseif instance and not func then
if msgObj[1] == instance then
table.remove(list, index)
end
elseif not instance and func then
if msgObj[2] == func then
table.remove(list, index)
end
end
end
end
--@desc 發送事件
--@arg msgId 消息Id息
Msg.Send = function(msgId, ...)
local list = Msg.msgmap[msgId]
if list then
for _, msgObj in pairs(list) do
if msgObj[2] then
msgObj[2](...)
end
end
end
end
Msg.init()
return Msg
MsgId.lua
用於存儲消息Id的腳本
MsgId = {}
MsgId.DOG_RUN = "DOG_RUN"
-- 簡單實現個只讀功能
setmetatable(MsgId, {__newindex = function()
print("new id must add in MsgId.lua")
end})
test.lua
其中的dog1,dog2,dog3,相當於消息監聽者,通過Msg.Add
函數監聽消息;Msg.Send
相當消息發送者,廣播對應的消息id
--[[
class 函數是自己實現的一個聲明類的函數
]]
local Dog = class("Dog", nil)
local dog1 = Dog.new()
local dog2 = Dog.new()
local dog3 = Dog.new()
dog3.AddMsg = function(self)
Msg.Add(self, MsgId.DOG_RUN, function(...)
print("dog3 跑, 通過外部添加監聽", ...)
end)
end
Msg.Add(dog1, MsgId.DOG_RUN, function(...)
print("dog1 跑, 通過外部添加監聽", ...)
end)
Msg.Add(dog2, MsgId.DOG_RUN, function(...)
print("dog2 跑, 通過外部添加監聽", ...)
end)
dog3:AddMsg()
Msg.Send(MsgId.DOG_RUN, "-> test 事件參數")
print("------------------------------------------")
Msg.Remove(MsgId.DOG_RUN, dog2)
Msg.Send(MsgId.DOG_RUN, "-> test 事件參數")
print("------------------------------------------")
--[[ 輸出信息:
dog1 跑, 通過外部添加監聽 -> test 事件參數
dog2 跑, 通過外部添加監聽 -> test 事件參數
dog3 跑, 通過外部添加監聽 -> test 事件參數
------------------------------------------
dog1 跑, 通過外部添加監聽 -> test 事件參數
dog3 跑, 通過外部添加監聽 -> test 事件參數
------------------------------------------
[Finished in 0.1s]
]]
在test腳本中,
- 3個監聽者分別監聽了
MsgId.DOG_RUN
消息 Msg.Send(MsgId.DOG_RUN, "-> test 事件參數")
進行了一次廣播Msg.Remove(MsgId.DOG_RUN, dog2)
將消息中心dog2
的MsgId.DOG_RUN
消息移除Msg.Send(MsgId.DOG_RUN, "-> test 事件參數")
又進行了一次廣播,因爲之前有移除過dog2
的對應消息,所以再次輸出中沒有dog2
的輸出。
更進階的還包括消息的優先級等