利用觀察者模式實現Cocos2DX-lua遊戲中的訊息管理系統
阿新 • • 發佈:2019-02-11
http://blog.csdn.net/operhero1990/article/details/48575487
遊戲中某些物件往往需要及時獲知其他特定物件狀體的改變。為降低類之間的耦合度,可以建立訊息管理系統,實現訊息的集中與分發。觀察者(也叫釋出-訂閱)模式很容易實現這套系統。觀察者模式是一種比較成熟的設計模式,基本概念可以通過百度獲得,這裡不再贅述。
訊息管理系統實際分為:管理中心,觀察者,訂閱者三部分。
一、管理中心
這裡先上實現程式碼:
-- -- file: msgCenter.lua -- desc: 訊息管理中心 --================================================ hp.msgCenter = {} -- 訊息定義 hp.MSG = { CHANGEDTYPE_1 = 1, --變化1 CHANGEDTYPE_2 = 2, --變化2 } -- 訊息處理者 local msgMgr = {} -- addMsgMgr -- 新增訊息處理 ----------------------------------------- function hp.msgCenter.addMsgMgr(msg_, mgr_) if msgMgr[msg_]==nil then msgMgr[msg_] = {} else for i,v in ipairs(msgMgr[msg_]) do if v==mgr_ then -- 已新增 return false end end end table.insert(msgMgr[msg_], mgr_) return true end -- removeMsgMgr -- 移除訊息處理 ----------------------------------------- function hp.msgCenter.removeMsgMgr(msg_, mgr_) if msgMgr[msg_]~=nil then for i,v in ipairs(msgMgr[msg_]) do if v==mgr_ then table.remove(msgMgr[msg_], i) break end end end return true end -- sendMsg -- 傳送訊息 ----------------------------------------- function hp.msgCenter.sendMsg(msg_, param_) if msgMgr[msg_]~=nil then for i,v in ipairs(msgMgr[msg_]) do v:onMsg(msg_, param_) end end end
hp.msgCenter:外部呼叫介面
訊息定義:訊息系統需要處理不同型別的訊息,這裡相當於訊息型別的巨集定義訊息處理者msgMgr:儲存訂閱者的表
新增訊息處理hp.msgCenter.addMsgMgr(msg_,mgr_):將訂閱者以及訂閱的訊息型別儲存於訊息處理者msgMgr表中。msg_為訊息定義巨集中的一種,mgr_為訂閱者
移除訊息處理hp.msgCenter.removeMsgMgr(msg_, mgr_):與新增訊息對應
傳送訊息hp.msgCenter.sendMsg(msg_, param_):由觀察者呼叫此方法,向所有訂閱者傳送引數param_。訂閱者通過自身onMsg方法接收並處理訂閱訊息。
二、觀察者
觀察者部分較為簡單,只需呼叫傳送訊息方法即可:hp.msgCenter.sendMsg(hp.MSG.CHANGEDTYPE_1, “訊息型別1”)
三、訂閱者
訂閱者主要分為兩步:註冊訊息和響應訊息處理
這裡我們構建一個訂閱者基類,提供訊息訂閱方法,並建立訊息訂閱表,方便物件析構時及時移除訊息訂閱
-- -- Listener.lua -- 訂閱者基類 --================================================ Listener = Listener or class("Listener") -- -- ctor ------------------------------- function Listener:ctor(...) self.super.init(self) self:init(...) end -- -- init ---------------------------- function Listener:init() self.manageMsg = {} end -- -- preExit ---------------------------- function Listener:preExit() self:unregistAllMsg() end -- -- onExit ---------------------------- function Listener:onExit() self:unregistAllMsg() end -- -- 訊息處理 --============================================= -- registMsg function Listener:registMsg(msg_) if hp.msgCenter.addMsgMgr(msg_, self) then table.insert(self.manageMsg, msg_) end end -- unregistMsg function Listener:unregistMsg(msg_) if hp.msgCenter.removeMsgMgr(msg_, self) then for i,v in ipairs(self.manageMsg) do if v==msg_ then table.remove(self.manageMsg, i) end end end end -- unregistMsg function Listener:unregistAllMsg() for i,v in ipairs(self.manageMsg) do hp.msgCenter.removeMsgMgr(v, self) end self.manageMsg = {} end -- onMsg function Listener:onMsg(msg_, parm_) end
其他類繼承訂閱者基類即可實現訊息訂閱功能:
-- file:MyListener.lua
-- desc:訂閱者
-- =====================================
MyListener = class("MyListener", Listener)
-- 初始化
function MyListener<span style="font-family: Arial, Helvetica, sans-serif;">:init()</span>
local function bindGuide(parm_)
print(parm_)
end
self.bindGuide = bindGuide
self:registMsg(hp.MSG.CHANGEDTYPE_1)
end
-- onMsg
function MyListener:onMsg(msg_, parm_)
if msg_==hp.MSG.CHANGEDTYPE_1 then
self.bindGuide(parm_)
end
end
MyListener首先訂閱hp.MSG.CHANGEDTYPE_1,onMsg接受訊息時,判斷髮過來的訊息是否為訂閱的型別,並呼叫相應的處理函式self.bindGuide處理訊息