六、JDK自帶觀察者

利用Java提供的Observer接口和Observable類實(shí)現(xiàn)觀察者模式

對于觀察者模式休吠,其實(shí)Java已經(jīng)為我們提供了已有的接口和類谒获。對于訂閱者(Subscribe蛤肌,觀察者)Java為我們提供了一個(gè)接口,JDK源碼如下:

1 package java.util;
2 
3 public interface Observer {
4     void update(Observable o, Object arg);
5 }

和我們上一篇實(shí)現(xiàn)的觀察者一樣批狱,僅提供一個(gè)update方法用于接收通知者的通知做出相應(yīng)改變寻定。

我們再來看看Java為我們提供了一個(gè)怎樣的通知者(Publish,發(fā)布者)精耐,JDK源碼如下:

package java.util;

public class Observable {
    private boolean changed = false;  //是否改變狀態(tài)
    private Vector obs;    //Vector利用同步方法來線程安全狼速,線程安全在多線程情況下不會造成數(shù)據(jù)混亂

    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);
    }

    public void notifyObservers() {
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)    //狀態(tài)值未改變時(shí)返回,不通知
                return;
            arrLocal = obs.toArray();  //將Vector轉(zhuǎn)換成數(shù)組
            clearChanged();    //重置狀態(tài)
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

    public synchronized boolean hasChanged() {
        return changed;
    }

    public synchronized int countObservers() {
        return obs.size();
    }
}

不得不說卦停,Java源碼考慮得就是比自己寫的要好向胡。首先,使用Vector惊完,Vector相比于ArrayList來說僵芹,它是線程安全的。其次小槐,在添加和刪除觀察者時(shí)對兩個(gè)方法使用了synchronized關(guān)鍵字拇派,這都是在為多線程考慮。確實(shí)Java源碼并不是那么可怕凿跳,它同樣也是由一些最簡單最基礎(chǔ)的組合而來件豌。

接下來我們來看看是如何利用Java提供的接口和方法來實(shí)現(xiàn)觀察者模式。

package day_10_observer_jdk;

import java.util.Observable;
import java.util.Observer;

/**
 * 實(shí)現(xiàn)java.util.Observer接口的觀察者
 * @author turbo
 *
 * 2016年9月14日
 */
public class Subscribe implements Observer {

    public Subscribe(Observable o){
        o.addObserver(this);        //將該觀察者放入待通知觀察者里
    }
    /* (non-Javadoc)
     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("收到通知:" + ((Publish)o).getData());
    }

}
package day_10_observer_jdk;

import java.util.Observable;

/**
 * 繼承java.util.Observable的通知者
 * @author turbo
 *
 * 2016年9月14日
 */
public class Publish extends Observable {
    private String data = "";

    public String getData() {
        return data;
    }

    public void setData(String data) {
        if (!this.data.equals(data)){
            this.data = data;
            setChanged();    //改變通知者的狀態(tài)
        }
        notifyObservers();    //調(diào)用父類Observable方法控嗜,通知所有觀察者
    }
}

客戶端測試代碼:

package day_10_observer_jdk;

/**
 * @author turbo
 *
 * 2016年9月14日
 */
public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Publish publish = new Publish();
        Subscribe subscribe = new Subscribe(publish);
        
        publish.setData("開始");
    }

}

這樣我們就利用了Java給我們提供的Observer接口和Observable類實(shí)現(xiàn)了觀察者模式茧彤。上一篇我們提到了事件委托,我們在下一篇來了解一下什么是事件委托疆栏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末曾掂,一起剝皮案震驚了整個(gè)濱河市惫谤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌珠洗,老刑警劉巖溜歪,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異许蓖,居然都是意外死亡蝴猪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門蛔糯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窖式,你說我怎么就攤上這事蚁飒。” “怎么了萝喘?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵淮逻,是天一觀的道長。 經(jīng)常有香客問我阁簸,道長爬早,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任启妹,我火速辦了婚禮筛严,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘饶米。我一直安慰自己桨啃,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布檬输。 她就那樣靜靜地躺著照瘾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丧慈。 梳的紋絲不亂的頭發(fā)上析命,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機(jī)與錄音逃默,去河邊找鬼鹃愤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛完域,可吹牛的內(nèi)容都是我干的昼浦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼筒主,長吁一口氣:“原來是場噩夢啊……” “哼关噪!你這毒婦竟也來了鸟蟹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤使兔,失蹤者是張志新(化名)和其女友劉穎建钥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虐沥,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡熊经,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了欲险。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镐依。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖天试,靈堂內(nèi)的尸體忽然破棺而出槐壳,到底是詐尸還是另有隱情,我是刑警寧澤喜每,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布务唐,位于F島的核電站,受9級特大地震影響带兜,放射性物質(zhì)發(fā)生泄漏枫笛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一刚照、第九天 我趴在偏房一處隱蔽的房頂上張望刑巧。 院中可真熱鬧,春花似錦无畔、人聲如沸海诲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽特幔。三九已至,卻和暖如春闸昨,著一層夾襖步出監(jiān)牢的瞬間蚯斯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工饵较, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拍嵌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓循诉,卻偏偏與公主長得像横辆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子茄猫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,140評論 25 707
  • 用兩張圖告訴你狈蚤,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料困肩? 從這篇文章中你...
    hw1212閱讀 12,724評論 2 59
  • 本文大約 1200字,建議閱讀時(shí)間 3分鐘脆侮。 在我12月22日發(fā)了《【培訓(xùn)名詞專場】4.4 顛倒課堂是什么鬼》之后...
    培訓(xùn)經(jīng)理陳維磊閱讀 399評論 0 0
  • 人的一生總有那么一段時(shí)光锌畸,稱得上花樣年華,即使你不美靖避,也可以拿來炫耀年輕的光彩潭枣。 茶,也是有生命的幻捏。 第一泡的茶湯...
    小危茶坐閱讀 174評論 0 0
  • 4.長公主 與黑澤暫時(shí)告別盆犁,櫻內(nèi)站在窗旁,一手抓著窗戶上檐篡九,左腳踏在窗塌上谐岁,向內(nèi)略一施力,再渡著些許內(nèi)力以右手為軸...
    持讋刀行者閱讀 589評論 0 0