java 中的觀察者模式

觀察者模式是一種常見的設(shè)計模式,顧名思義有觀察者與被觀察者剔宪,被觀察者的狀態(tài)有變動會通知觀察者拂铡,觀察者會收到通知壹无,進(jìn)而做進(jìn)一步的操作

要實現(xiàn)觀察者模式我們要首先思考下面幾個問題:

1. 觀察者的實現(xiàn)

2. 被觀察者的實現(xiàn)

3. 被觀察者狀態(tài)變更是怎么通知觀察者

4. 觀察者收到通知如何處理接下來的行為

### 觀察者的實現(xiàn)

`

public interface Observer {

? ? void update(Observable o, Object arg);

}

`

java提供了一個Observer接口,并有一個 update 方法感帅。觀察者只需要實現(xiàn)Observer接口斗锭,并實現(xiàn)update方法,表示收到被觀察者變更通知之后的行為

`

public class CurrentCondition implements Observer {

? ? private float temperature;

? ? private float pressure;

? ? private float humitidy;

? ? public void display(){

? ? ? ? System.out.println(temperature+","+pressure+","+humitidy);

? ? }

? ? @Override

? ? public void update(Observable o, Object arg) {

? ? ? ? this.temperature = ((WetherData)o).getTemperature();

? ? ? ? this.pressure = ((WetherData)o).getPressure();

? ? ? ? this.humitidy = ((WetherData)o).getHumidity();

? ? ? ? display();

? ? }

}

`

### 被觀察者

同樣java提供了Observable類失球,被觀察者需要繼承該類

`

public class Observable {

? ? private boolean changed = false;


? //用來保存觀察者岖是,遍歷發(fā)通知

? ? private Vector<Observer> obs;


? ? public Observable() {

? ? ? ? obs = new Vector<>();

? ? }

? ? /**

? ? ? ? 添加觀察者

? ? */

? ? public synchronized void addObserver(Observer o) {

? ? ? ? if (o == null)

? ? ? ? ? ? throw new NullPointerException();

? ? ? ? if (!obs.contains(o)) {

? ? ? ? ? ? obs.addElement(o);

? ? ? ? }

? ? }

? ? /**

? ? 刪除觀察者

? ? */

? ? public synchronized void deleteObserver(Observer o) {

? ? ? ? obs.removeElement(o);

? ? }

? ? /*

? ? 當(dāng)本觀察者發(fā)生變化,需要先講change設(shè)置為true实苞,就會通知所有的注冊在 obs 變量里的觀察者豺撑,

? ? 會調(diào)用觀察者實現(xiàn)的update方法

? ? 再用clearChange方法將change設(shè)為false,表示不再變化


? ? */

? ? public void notifyObservers() {

? ? ? ? notifyObservers(null);

? ? }


? ? public void notifyObservers(Object arg) {

? ? ? ? Object[] arrLocal;

? ? ? ? synchronized (this) {

? ? ? ? ? ? if (!changed)

? ? ? ? ? ? ? ? return;

? ? ? ? ? ? arrLocal = obs.toArray();

? ? ? ? ? ? clearChanged();

? ? ? ? }

? ? ? ? for (int i = arrLocal.length-1; i>=0; i--)

? ? ? ? ? ? ((Observer)arrLocal[i]).update(this, arg);

? ? }

? ? /**

? ? * Clears the observer list so that this object no longer has any observers.

? ? */

? ? public synchronized void deleteObservers() {

? ? ? ? obs.removeAllElements();

? ? }

? ? /**

? ? * Marks this <tt>Observable</tt> object as having been changed; the

? ? * <tt>hasChanged</tt> method will now return <tt>true</tt>.

? ? */

? ? protected synchronized void setChanged() {

? ? ? ? changed = true;

? ? }

? ? /**

? ? * Indicates that this object has no longer changed, or that it has

? ? * already notified all of its observers of its most recent change,

? ? * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.

? ? * This method is called automatically by the

? ? * <code>notifyObservers</code> methods.

? ? *

? ? * @see? ? java.util.Observable#notifyObservers()

? ? * @see? ? java.util.Observable#notifyObservers(java.lang.Object)

? ? */

? ? protected synchronized void clearChanged() {

? ? ? ? changed = false;

? ? }

? ? /**

? ? * Tests if this object has changed.

? ? *

? ? * @return? <code>true</code> if and only if the <code>setChanged</code>

? ? *? ? ? ? ? method has been called more recently than the

? ? *? ? ? ? ? <code>clearChanged</code> method on this object;

? ? *? ? ? ? ? <code>false</code> otherwise.

? ? * @see? ? java.util.Observable#clearChanged()

? ? * @see? ? java.util.Observable#setChanged()

? ? */

? ? public synchronized boolean hasChanged() {

? ? ? ? return changed;

? ? }

? ? /**

? ? * Returns the number of observers of this <tt>Observable</tt> object.

? ? *

? ? * @return? the number of observers of this object.

? ? */

? ? public synchronized int countObservers() {

? ? ? ? return obs.size();

? ? }

}

`

實現(xiàn)如下:

`

public class WetherData extends Observable {

? ? private float temperature;

? ? private float pressure;

? ? private float humidity;

? ? public float getTemperature() {

? ? ? ? return temperature;

? ? }

? ? public void setTemperature(float temperature) {

? ? ? ? this.temperature = temperature;

? ? }

? ? public float getPressure() {

? ? ? ? return pressure;

? ? }

? ? public void setPressure(float pressure) {

? ? ? ? this.pressure = pressure;

? ? }

? ? public float getHumidity() {

? ? ? ? return humidity;

? ? }

? ? public void setHumidity(float humidity) {

? ? ? ? this.humidity = humidity;

? ? }

? ? public void setData(float temperature,float pressure,float humidity){

? ? ? ? this.temperature = temperature;

? ? ? ? this.pressure = pressure;

? ? ? ? this.humidity = humidity;

? ? ? //需要先調(diào)用setChanged()方法黔牵,

? ? ? ? setChanged();

? ? ? ? notifyObservers();? //這個方法里面會將change的狀態(tài)清除

? ? }

}

`

`

public class Wether {

? ? public static void main(String[] args) {

? ? ? ? WetherData wetherData = new WetherData();

? ? ? ? CurrentCondition currentCondition = new CurrentCondition();

? ? ? ? wetherData.addObserver(currentCondition);

? ? ? ? wetherData.setData(112,22,221);

? ? }

}

`

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末聪轿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子猾浦,更是在濱河造成了極大的恐慌屹电,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跃巡,死亡現(xiàn)場離奇詭異危号,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)素邪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門外莲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兔朦,你說我怎么就攤上這事偷线。” “怎么了沽甥?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵声邦,是天一觀的道長。 經(jīng)常有香客問我摆舟,道長亥曹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任恨诱,我火速辦了婚禮媳瞪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘照宝。我一直安慰自己蛇受,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布厕鹃。 她就那樣靜靜地躺著兢仰,像睡著了一般乍丈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上把将,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天轻专,我揣著相機(jī)與錄音,去河邊找鬼秸弛。 笑死,一個胖子當(dāng)著我的面吹牛洪碳,可吹牛的內(nèi)容都是我干的递览。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瞳腌,長吁一口氣:“原來是場噩夢啊……” “哼绞铃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嫂侍,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤儿捧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后挑宠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菲盾,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年各淀,在試婚紗的時候發(fā)現(xiàn)自己被綠了懒鉴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡碎浇,死狀恐怖临谱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情奴璃,我是刑警寧澤悉默,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站苟穆,受9級特大地震影響抄课,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜雳旅,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一剖膳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧岭辣,春花似錦吱晒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叹话。三九已至,卻和暖如春墩瞳,著一層夾襖步出監(jiān)牢的瞬間驼壶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工喉酌, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留热凹,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓泪电,卻偏偏與公主長得像般妙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子相速,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355