觀察者模式


title: 觀察者模式
date: 2016-07-19 23:15:36
tags: 編程
categories: 設計模式


定義

觀察者模式是軟件設計模式的一種。在此種模式中,一個目標對象管理所有相依于它的觀察者對象唤衫,并且在它本身的狀態(tài)改變時主動發(fā)出通知祖乳。這通常透過呼叫各觀察者所提供的方法來實現(xiàn)嘁字。此種模式通常被用來實時事件處理系統(tǒng)码倦。

觀察者模式的作用

1.當抽象個體有兩個互相依賴的層面時咽块。封裝這些層面在單獨的對象內將可允許程序員單獨地去變更與重復使用這些對象忽洛,而不會產生兩者之間交互的問題腻惠。
2.當其中一個對象的變更會影響其他對象,卻又不知道多少對象必須被同時變更時欲虚。
3.當對象應該有能力通知其他對象集灌,又不應該知道其他對象的實做細節(jié)時。

在mvc上的應用

觀察者模式通常與 MVC 范式有關系复哆。在 MVC 中欣喧,觀察者模式被用來降低 model 與 view 的耦合程度。一般而言梯找, model 的改變會觸發(fā)通知其他身為觀察者的 model 唆阿。而這些 model 實際上是 view

觀察者的時序圖


抽象主題(Subject):它把所有觀察者對象的引用保存到一個聚集里,每個主題都可以有任何數(shù)量的觀察者锈锤。抽象主題提供一個接口驯鳖,可以增加和刪除觀察者對象。
具體主題(ConcreteSubject):將有關狀態(tài)存入具體觀察者對象久免;在具體主題內部狀態(tài)改變時浅辙,給所有登記過的觀察者發(fā)出通知。
抽象觀察者(Observer):為所有的具體觀察者定義一個接口阎姥,在得到主題通知時更新自己记舆。 具體觀察者(ConcreteObserver):實現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題狀態(tài)協(xié)調呼巴。

實現(xiàn)

全局掌握
在氣象觀測站中泽腮,它能夠追蹤目前的天氣狀況,包括溫度衣赶、適度诊赊、氣壓。需要實現(xiàn)一個布告板屑埋,能夠分別顯示目前的狀態(tài)豪筝,氣象統(tǒng)計和簡單的預報痰滋。當氣象站中獲取最新的測量數(shù)據(jù)時摘能,三種布告板必須實時更新续崖。當然可以直接擴展布告板,不過首先要向主題注冊团搞,才能夠在主題更新的時候更新布告板的信息严望,分析圖如下:



就像現(xiàn)在非常流行的rss訂閱,當你訂閱的時候逻恐,主題者會把你的注冊信息添加像吻,當主題要發(fā)布新的信息的時候,你接受到的更新會更新你自己的觀察者的信息复隆,呈現(xiàn)給閱讀者看
觀察者模式解決了主題更新拨匆,觀察者就要修改源代碼的麻煩,降低了耦合度挽拂,實現(xiàn)了抽象和實體的分離惭每,為三層架構提供了可能。

代碼實現(xiàn)

代碼接口
---Java
public interface Subject {
/**
* 注冊觀察者
* @param observer
*/
public void registerObserver(Observer observer);

/**
 * 刪除觀察者
 * @param observer
 */  
public void removeOberver(Observer observer);  

/**
 * 當主題狀態(tài)發(fā)生改變時亏栈,這個方法需要被調用台腥,以通知所有觀察者
 */  
public void notifyObserver();  

}

    觀察者接口  

---java
public interface Observer {
public void update(float temp,float humidity,float pressure);
}



public interface DisplayElement {
public void display();
}


主題實現(xiàn)

public class WeatherData implements Subject{
private List<Observer> observers;
private float tempterature;
private float pressure;
private float humidity;

public WeatherData(){  
    observers = new ArrayList<Observer>();  
}  

@Override  
public void notifyObserver() {  
    for(int i = 0; i < observers.size();i++){  
        Observer observer = observers.get(i);  
        observer.update(tempterature, humidity, pressure);  
    }  
}  

@Override  
public void registerObserver(Observer observer) {  
    observers.add(observer);  
}  

@Override  
public void removeOberver(Observer observer) {  
    int i = observers.indexOf(observer);  
    if(i >= 0){  
        observers.remove(i);  
    }  
}  

/**
 * 氣象站得到更新的觀測數(shù)據(jù)時,通知觀察者
 */  
public void measurementChanged(){  
    notifyObserver();  
}  

public void setMeasurements(float temperature,float humidity,float pressure){  
    this.tempterature = temperature;  
    this.humidity = humidity;  
    this.pressure = pressure;  
    measurementChanged();  
}  

}


public class CurrentConditionsDisplay implements Observer,DisplayElement{
private float temperature;
private float humidity;
private Subject weatherData;

public CurrentConditionsDisplay(Subject weatherData){  
    this.weatherData = weatherData;  
    weatherData.registerObserver(this);      //注冊觀察者  
}  

public void update(float temp, float humidity, float pressure) {  
    this.temperature = temp;  
    this.humidity = humidity;  
    display();  
}  

@Override  
public void display() {  
    System.out.println("Current conditions:"+temperature+"F degrees and "+humidity+"% humidity");  
}  

}

測試類

package weatherDataTest;

public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData=new WeatherData();
CurrentConditionDisplay currentDisplay=new CurrentConditionDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.5f);
weatherData.setMeasurements(83, 55, 29.7f);
weatherData.setMeasurements(78 , 90, 34.2f);

}

}


/*
總結:
觀察者模式是設計一個程序的一個很重要的模式绒北,實現(xiàn)了實體和邏輯的分離黎侈,在控制中就能夠控制view層的活動,可以更加靈活的 去開發(fā)軟件闷游,讓自己有更多的時間去關注于軟件的業(yè)務功能峻汉,提高了開發(fā)效率
本文的例子來自《head first 設計模式》

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市脐往,隨后出現(xiàn)的幾起案子俱济,更是在濱河造成了極大的恐慌,老刑警劉巖钙勃,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛛碌,死亡現(xiàn)場離奇詭異,居然都是意外死亡辖源,警方通過查閱死者的電腦和手機蔚携,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來克饶,“玉大人酝蜒,你說我怎么就攤上這事》龋” “怎么了亡脑?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我霉咨,道長蛙紫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任途戒,我火速辦了婚禮坑傅,結果婚禮上,老公的妹妹穿的比我還像新娘喷斋。我一直安慰自己唁毒,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布星爪。 她就那樣靜靜地躺著浆西,像睡著了一般。 火紅的嫁衣襯著肌膚如雪顽腾。 梳的紋絲不亂的頭發(fā)上室谚,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音崔泵,去河邊找鬼秒赤。 笑死,一個胖子當著我的面吹牛憎瘸,可吹牛的內容都是我干的入篮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼幌甘,長吁一口氣:“原來是場噩夢啊……” “哼潮售!你這毒婦竟也來了?” 一聲冷哼從身側響起锅风,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤酥诽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后皱埠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肮帐,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年边器,在試婚紗的時候發(fā)現(xiàn)自己被綠了训枢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡忘巧,死狀恐怖恒界,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情砚嘴,我是刑警寧澤十酣,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布涩拙,位于F島的核電站,受9級特大地震影響耸采,放射性物質發(fā)生泄漏兴泥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一洋幻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧翅娶,春花似錦文留、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蜕提,卻和暖如春森书,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谎势。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工凛膏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脏榆。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓猖毫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親须喂。 傳聞我的和親對象是個殘疾皇子吁断,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內容