1. 程式人生 > >設計模式在遊戲開發中的應用之觀察者模式

設計模式在遊戲開發中的應用之觀察者模式

觀察者模式

1.通俗的定義

        觸發事件的一方不關心誰來處理,處理事件的一方不關心事件是從哪裡來的。觀察者模式就是讓觀察者與被觀察者徹底解耦。

2.2.結構圖如下(圖片來源與網路):


3.遊戲開發中的使用

        當我們設計一個成就係統的時候,往往要在各個系統都要增加判斷,比如殺死某種怪物多少隻,新手往往可能這麼寫:

public static KILL_1009_COUNT = 0;
main () {
	//killMonster是殺死一個怪物,返回殺死怪物的id
	int id = killMonster();
	//如果殺死的怪物是1009那麼數量加一,超過100次達成成就
	if (id == "1009") {
		KILL_1009_COUNT++;
		if (KILL_1009_COUNT > 100) {
			print("達成成就!殺死1009怪物100次!");
		}
	}
}
       如果這樣寫下去,後果將不堪設想:各個類直接將會超級耦合,成就判斷將會蔓延到整個專案的每個角落!觀察者模式就是為了解決這個問題而出現的。觀察者模式讓程式碼徹底解耦,還是上面的那個例子:
main () {
	//killMonster是殺死一個怪物,返回殺死怪物的id
	int id = killMonster();
	//傳送訊息,殺死怪物,並將殺死的怪物id一起傳送
	notify(EVENT_KILL_MONSTER, id);
}
       這樣程式碼的各個功能就不用關心成就相關的邏輯,只是通知我做了這樣一件事情就可以了。同樣,遊戲中這樣的例子到處都是,比如增加經驗時,我們傳送增加經驗的訊息,接收訊息的地方來處理到底升沒升級,因為可以增加經驗的地方有很多,這樣我們就不用匯出判斷是否升級了。
       下面看一下觀察者的實現:
//處理觀察者與被觀察者
class Notification {
	//一個可變的觀察者列表
	private List observerList = null;
	//該類是單例(後面我們會單獨講單例模式)
	private static Notification _instance = null;	
	public static getInstance() {
		if (_instance == null) {
			_instance = new Notification();
			//初始化列表容器
			observerList = new ArrayList();
		}
		return _instance;
	}
	//新增觀察者
	public void addObserver(Observer obs) {
		if (!observerList.isExistobs {
			observerList.add(obs);
		}
	}
	//刪除觀察者
	public void removeObserver(Observer obs) {
		observerList.remove(obs);
	}
	
	//廣播訊息
	public void sendMsg(String event, ..) {
		for (Observer obs : observerList) {
			if (obs.event == event) {
				obs.onNotify(..);
			}
		}
	}
}

//觀察者基類
class Observer {
	String event;
	//接收訊息函式,event是訊息型別,後面是引數
	void onNotify(..)
	//新增觀察者
	void addObserver(String event) {
		event = event;
		Notification.getInstance().addObserver(this);
	}
}

//殺怪成就觀察者
class AchievementObserver extends Observer {
	void onNotify(id) {
		if (id == 1009) {
			//處理殺1009怪的成就邏輯
		} else if (id == 1010) {
			//處理殺1010怪的成就邏輯
		}
	}
}

main () {
	//killMonster是殺死一個怪物,返回殺死怪物的id
	int id = killMonster();
	//傳送訊息,殺死怪物,並將殺死的怪物id一起傳送
	Notification.getInstance().sendMsg(EVENT_KILL_MONSTER, id);
}
         然後在寫一個成就管理類來管理各種成就觀察者,這樣各個成就直接也可以解耦。

      其他問題:

      1.引用銷燬問題:這個問題容易造成記憶體洩漏,就是在這個觀察者不再使用時,一定記得將其remove,否則這個觀察者一直在引用著,不會被釋放。

      2.同步非同步問題:sendMsg這個函式中是在主執行緒按加入順序進行傳送的,在特殊情況下根據需要可以使用多執行緒來實現。

      3.其他應用:觀察者模式在MVC這種結構下也經常使用,control來處理邏輯,通過觀察者來相應UI事件。

      觀察者模式的優點就是可以做到完全的解耦;缺點就是使用不當會讓程式難以維護和除錯。

關注我的公眾號Ituuz_coder,第一時間推送新文章: