1. 程式人生 > >Cocos2d-x設計模式之六 :觀察者模式

Cocos2d-x設計模式之六 :觀察者模式

1、應用場景

前面在介紹單例模式的時候,提到了一個類CCNotificationCenter,它除了應用單例模式以外,還應用了觀察者模式。CCNotificationCenter類是觀察者模式中的目標物件,而CCNotificationObserver則是觀察者。

一個目標物件可以註冊多個觀察者,當目標物件的狀態改變的時候,可以通知觀察者物件作出相應的響應。這是標準的觀察者模式的實現,但是CCNotificationCenter稍微有些許差別。

首先,CCNotificationCenter不是通過自身狀態改變來通知觀察者,而是通過顯式地傳送觀察者感興趣的訊息(postNotification)來通知它們。每一種訊息型別可以對應多個觀察者,同時,每一個觀察者也可以“觀察”多個訊息型別。其次,觀察者定義相應的響應事件同訊息型別關聯,當某個地方觸發postNotification來廣播一個訊息的時候,CCNotificationCenter會遍歷所有的觀察者,判斷它們註冊的訊息型別是否匹配,如果匹配,則觸發相應的註冊響應事件。最後,該觀察者模式採用的是推模型,即由目標物件去通知所有的觀察者。

其實CCNotificationCenter和CCNotificationObserver更準確的叫法是:訂閱釋出模式

2、使用此模式的優缺點

優點:

1)實現了目標物件和觀察者之間的抽象耦合,在本例中,則是實現了訊息與觀察者的抽象耦合。可以定義一種訊息與訊息處理物件的一對多的關係,而不用擔心彼此的實現細節。

2)觀察者模式可以定義某種意義上的廣播通訊機制。

3)實現訂閱者與釋出者的鬆散耦合,同時保障了良好的擴充套件性。

缺點:

1)註冊成為CCNotificationCenter的觀察者後,如果忘記呼叫removeObserver,則會引起記憶體洩漏。因為addObserver會把觀察者的引用計算加1.

3、此模式的定義及一般實現

定義:

定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新。

UML圖:

一般實現:參考CCNotificationCenter.h和CCNotification.cpp檔案的實現

4、遊戲開發中如何運用此模式

我們考慮cocos2d-x中一個非常典型的應用場景,你的GameScene裡面有兩個layer,一個gameLayer,它包含了遊戲中的物件,比如玩家、敵人等。另一個層是HudLayer,它包含了遊戲中顯示分數、生命值等資訊。如何讓這兩個層相互通訊。

第一種辦法,你可以讓gameLayer包含一個hudLayer的引用,同時也可以讓hudLayer包含一個gameLayer的引用。注意!這裡問題出現了,如果兩個類都包含彼此的強引用(所謂強引用就是retain),就會引起迴圈引用的情況,如果其中一個類包含的是弱引用,問題就不會出現。迴圈引用是使用引用計數管理記憶體的一個致命弱點,會導致資源永遠得不到釋放,而且查錯起來非常麻煩。

第二種辦法,把gameScene做成一個單例,同時讓gameScene包含gameLayer和hudLayer的弱引用,這樣就可以直接通過[GameScene sharedInstance].gameLayer或者[GameScene sharedInstance].hudLayer來訪問了。

第三種辦法,使用gameLayer->getParent()獲得gameScene,再使用gameScene來獲得hudLayer。

第四種辦法,使用CCNotificationCenter。當hudLayer註冊它感興趣的訊息,當gameLayer需要通知hudLayer的時候,只需通過CCNotificationCenter傳送一個對應的訊息即可。

5、此模式與其它模式的關係

觀察者模式是實現MVC模式的重要組成部分,一個model可以對應多個views,model就是目標物件,而view則是觀察者,當model改變的時候,要通知所有的view也相應的改變。

歡迎讀者批評指正,如果有興趣跟我一起挖掘cocos2d-x中所涉及到的設計模式的朋友,可以給我發郵件:[email protected]或者直接留言。