概念
??觀察者模式:又稱發(fā)布(publish)-訂閱(Subscribe)模式悬槽、模型(Model)-視圖(View)模式唾那、源(Source)-監(jiān)聽器(Listener)模式或從屬者(Dependents)模式,是一種對象行為型模式喧锦。
??定義對象間的一對多的依賴關(guān)系庞呕,當被觀察者對象進行狀態(tài)改變時扯夭,則所有依賴它的觀察者對象都會得到通知并更新狀態(tài)遵倦。
UML
角色
- 抽象主題(Subject):又稱抽象被觀察者(Observable),抽象主題維護一個集合额嘿,用來保存所有觀察者對象的引用瘸恼。提供一個接口,用來添加或刪除觀察者對象册养。
- 具體主題(ConcreteSubject):又稱具體被觀察者(ConcreteObservable)吨枉,在具體主題狀態(tài)發(fā)生改變時炉抒,給所有注冊該主題的具體觀察者對象發(fā)出通知腮介。
- 抽象觀察者(Observer):觀察者的抽象類续搀,定義了一個update接口,得到主題更新的通知后坎炼,更新自己愧膀。
- 具體觀察者(ConcreteObserver):實現(xiàn)抽象觀察者的update接口,給出具體的更新狀態(tài)谣光。
簡單示例
??笑傲江湖中辟邪劍譜一重出江湖檩淋,就引起了各大門派的覬覦,這就是典型的觀察者模式啊萄金。福威鏢局被觀察者蟀悦、五岳劍派各大掌門等人為觀察者,觀察者模式開啟氧敢。
抽象主題(Observable)
java.util庫Observer源碼
package java.util;
public class Observable {
private boolean changed = false;
private final ArrayList<Observer> observers;
public Observable() {
observers = new ArrayList<>();
}
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!observers.contains(o)) {
observers.add(o);
}
}
public synchronized void deleteObserver(Observer o) {
observers.remove(o);
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Observer[] arrLocal;
synchronized (this) {
if (!hasChanged())
return;
arrLocal = observers.toArray(new Observer[observers.size()]);
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
arrLocal[i].update(this, arg);
}
public synchronized void deleteObservers() {
observers.clear();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return observers.size();
}
}
具體主題(ConcreteSubject)
福威鏢局
package com.bamboolmc.designpattern.ObserverMode;
import java.util.Observable;
public class FuWeiBoard extends Observable{
//發(fā)布事件--辟邪劍譜重現(xiàn)江湖
public void publishPiXie(){
System.out.println("我福威鏢局日戈,辟邪劍譜重現(xiàn)江湖");
//標志狀態(tài)修改
setChanged();
//通知所有觀察者
notifyObservers();
}
}
抽象觀察者(Observer)
java.util庫Observer接口源碼
package java.util;
public interface Observer {
void update(Observable o, Object arg);
}
具體觀察者(ConcreteObserver)
林平之、岳不群福稳、余滄海
package com.bamboolmc.designpattern.ObserverMode;
import java.util.Observable;
import java.util.Observer;
public class LinPingzhi implements Observer {
public LinPingzhi() {
}
@Override
public void update(Observable o, Object arg) {
doSomething();
}
private void doSomething() {
System.out.println("我林平之涎拉,這是我家祖?zhèn)鲃Ψǎ ? 先要自* &^*$*% 神功已成的圆,我終于可以報仇了");
}
}
package com.bamboolmc.designpattern.ObserverMode;
import java.util.Observable;
import java.util.Observer;
public class YuCanghai implements Observer {
public YuCanghai() {
}
@Override
public void update(Observable o, Object arg) {
doSomething();
}
private void doSomething() {
System.out.println("我余滄海鼓拧,江湖傳聞的第一劍譜,是我的越妈!………… 我擦季俩,沒搶到,晦氣梅掠!");
}
}
package com.bamboolmc.designpattern.ObserverMode;
import java.util.Observable;
import java.util.Observer;
public class YueBuqun implements Observer{
public YueBuqun() {
}
@Override
public void update(Observable o, Object arg) {
doSomething();
}
private void doSomething(){
System.out.println("我岳不群酌住,有了劍譜,我就是五岳盟主阎抒! …… \"欲練此功酪我,必先自*\" 咔@%#&* 神功在體,誰敢跟我奪五岳盟主^_^");
}
}
觀察者模式使用
package com.bamboolmc.designpattern.ObserverMode;
import java.util.Observable;
public class FuWeiBoard extends Observable{
//發(fā)布事件--辟邪劍譜重現(xiàn)江湖
public void publishPiXie(){
System.out.println("我福威鏢局且叁,辟邪劍譜重現(xiàn)江湖");
//標志狀態(tài)修改
setChanged();
//通知所有觀察者
notifyObservers();
}
}
輸出結(jié)果
我福威鏢局都哭,辟邪劍譜重現(xiàn)江湖
我岳不群,有了劍譜逞带,我就是五岳盟主欺矫! …… "欲練此功,必先自*" 咔@%#&* 神功在體展氓,誰敢跟我奪五岳盟主^_^
我余滄海穆趴,江湖傳聞的第一劍譜,是我的遇汞!………… 我擦未妹,沒搶到,晦氣勺疼!
我林平之教寂,這是我家祖?zhèn)鲃Ψǎ ? 先要自* &^*$*% 神功已成执庐,我終于可以報仇了
適用環(huán)境
- 一個系統(tǒng)多個的對象對某些特定的對象的狀態(tài)或者屬性改變感興趣,就可以采取該模式酪耕。
- 事件多級觸發(fā)場景。
- 消息隊列轨淌,事件總線處理機制
作用
??最重要的作用就是解耦迂烁,將被觀察者和觀察者解耦,使其依賴性更小或者毫無依賴递鹉。