1. 程式人生 > >利用觀察者模式實現Cocos2DX-lua遊戲中的訊息管理系統

利用觀察者模式實現Cocos2DX-lua遊戲中的訊息管理系統

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處理訊息