設計模式系列之「觀察者模式」

YoungManSter發表於2018-01-15

最近小Y在看《反黑》這部劇,最引人回味的是堪稱經典的山雞哥飛上枝頭變鳳凰,當初的古惑仔棄暗投明做警察,可謂是涅槃重生啊。

張sir: 山雞,和興盛最近很囂張啊,該是你大展身手的時候了,你要以最短時間打入他們內部獲取犯罪證據,同時你要更名為鳳凰,UnderStand?

鳳凰仔: Yes,Sir。

經過一段時間潛伏,鳳凰哥終於打入和興盛內部,成為韓彬的一把手。時刻監視著大佬們的一舉一動。

鳳凰仔: 張sir,和興盛大佬們齊聚一起,準備搞場大龍鳳,你立馬拖班人馬過來壓壓驚,順便來了一鍋端。

根據鳳凰監提供的證據,警方成功把這個社團搞得雞飛狗跳。最後鳳凰仔用槍指著韓彬的頭來了一句:一直在你身邊的警察,是我。來了一個一百八十度的轉彎,山雞變鳳凰。

鳳凰哥、Laughing哥是港劇臥底的佼佼者,讓人讚不絕口。在設計模式中,照樣有充當這樣角色的存在——觀察者模式

一、基本概念

1.定義

觀察者模式也叫做釋出訂閱模式,定義物件間一種一對多的依賴關係,使得每當一個物件改變狀態,則所有依賴於它的物件都會得到通知並被自動更新。

2.角色介紹

設計模式系列之「觀察者模式」

  • Subject被觀察者
    定義被觀察者必須實現的職責,它必須能夠動態地增加、取消觀察者。它一般是抽象類或者是實現類,僅僅完成作為被觀察者必須**實現的職責:**管理觀察者並通知觀察者。

  • Observer觀察者
    觀察者接收到訊息後,即進行update(更新方法)操作,對接收到的資訊進行處理。

  • ConcreteSubject具體的被觀察者
    定義被觀察者自己的業務邏輯,同時定義對哪些事件進行通知。

  • ConcreteObserver具體的觀察者
    每個觀察在接收到訊息後的處理反應是不同,各個觀察者有自己的處理邏輯。

3.觀察者模式的使用場景

  • 跨系統的訊息交換場景,如訊息佇列的處理機制。
  • 關聯行為場景。需要注意的是,關聯行為是可拆分的,而不是“組合”關係。
  • 事件多級觸發場景。

二、觀察者模式演繹山雞變鳳凰

在反黑組在監視這幾位大佬的同時,商業調查科等等其他警察部門也在監視著,為了使各部門行動統一,鳳凰仔收集到的證據統一使用,根據其反饋回來的訊息,各部門做相應的準備。

1.具體角色分配UML

設計模式系列之「觀察者模式」

2.程式碼實現

①和興盛的抽象被觀察者

public abstract class HeXingSheng {

	//儲存監視和興的警察部門
	private List<Police> polices=new ArrayList<>();
	//增加監聽的警察部門
	public abstract void addPoliceObserver(Police police);
	//刪除監聽的警察部門
	public abstract void deletePoliceObserver(Police police);
	//通知每個監聽部門作出反應
	public abstract void notifyPolices(String tip);

}
複製程式碼

②和興盛大佬們的具體被觀察類

public class HeadOfGang extends HeXingSheng {
	@Override
	public void addPoliceObserver(Police police) {
		this.polices.add(police);
	}

	@Override
	public void deletePoliceObserver(Police police) {
		this.polices.remove(police);
	}

	@Override
	public void notifyPolices(String tip) {
		for(Police police:polices){
			police.action(tip);
		}
	}
}
複製程式碼

③警察部門的抽象觀察者

public abstract class Police {
	//根據資訊作出反應
	public abstract void action(String action);
}
複製程式碼

④反黑組

public class FanHeiTeam extends Police {
	@Override
	public void action(String action) {
		System.out.println("臥底鳳凰提供的情報:"+action);
		System.out.println("反黑組根據情報對和興盛進行相關黑社會行為進行控告。");
	}
}
複製程式碼

⑤商業調查科

public class ShangYeTeam extends Police{

	@Override
	public void action(String action) {
		System.out.println("臥底鳳凰提供的情報:"+action);
		System.out.println("商業調查科根據情報對和興盛進行相關商業行為進行控告。");
	}
}
複製程式碼

⑥Client

public class Client {

	public static void main(String[] args) {
		//被觀察的物件-和興盛
		HeXingSheng xingSheng=new HeadOfGang();
		//觀察物件-反黑組、商業調查科
		Police fanHeiTeam=new FanHeiTeam();
		Police shangye=new ShangYeTeam();
		//增加觀察者
		xingSheng.addPoliceObserver(fanHeiTeam);
		xingSheng.addPoliceObserver(shangye);
		//鳳凰仔收集到證據,通知各部門準備行動
		xingSheng.notifyPolices("和興盛大佬們聚在一起搞龍鳳。");
	}
}
複製程式碼

輸出的結果為:

//反黑組 
臥底鳳凰提供的情報:和興盛大佬們聚在一起搞龍鳳。
反黑組根據情報對和興盛進行相關黑社會行為進行控告。

//商業調查科
臥底鳳凰提供的情報:和興盛大佬們聚在一起搞龍鳳。
商業調查科根據情報對和興盛進行相關商業行為進行控告。
複製程式碼

三、觀察者模式優缺點

1.優點

  • 觀察者模式支援廣播通訊。被觀察者會向所有的登記過的觀察者發出通知。
  • 觀察者和被觀察者之間是抽象耦合。則不管是增加觀察者還是被觀察者都非常容易擴充套件,而且在Java中都已經實現的抽象層級的定義,在系統擴充套件方面更是得心應手。

2.缺點

  • 如果一個被觀察者物件有很多直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間,效率讓人擔憂。

  • 一個被觀察者,多個觀察者,開發和除錯就會比較複雜,而且在Java中訊息的通知預設是順序執行,一個觀察者卡殼,會影響整體的執行效率。在這種情況下,一般考慮採用非同步的方式。

四、總結

觀察者模式在專案中非常常用,但是從上面頁面知道觀察者模式也相對存在著缺點,一是廣播鏈的問題。另外一個就是非同步處理問題,在開發中需要格外注意。

Android技術交流吧

相關文章