01.觀察者模式

01.觀察者模式

1计贰、認(rèn)識觀察者模式:

我們看看報(bào)紙和雜志的訂閱是怎么回事:

(1)報(bào)社的業(yè)務(wù)就是出版報(bào)紙筷笨。

(2)向某家報(bào)社訂閱報(bào)紙拐袜,只要他們有新報(bào)紙出版冯凹,就會(huì)給你送來谎亩。只要你是他們的訂戶,你就會(huì)一直收到新報(bào)紙宇姚。

(3) 當(dāng)你不想再看報(bào)紙的時(shí)候团驱,取消訂閱,他們就不會(huì)再送新報(bào)紙來空凸。

(4)只要報(bào)社還在運(yùn)營嚎花,就會(huì)一直有人(或單位)向他們訂閱報(bào)紙或者取消訂閱報(bào)紙。

2呀洲、定義:

觀察者模式定義了對象之間的一對多依賴紊选,這樣一來,當(dāng)一個(gè)對象改變狀態(tài)時(shí)道逗,它的所有依賴者都會(huì)收到通知并自動(dòng)更新兵罢。

主題和觀察者定義了一對多的關(guān)系。觀察者依賴于此主題滓窍,只要主題狀態(tài)一有變化卖词,觀察者就會(huì)被通知。根據(jù)通知的風(fēng)格,觀察者可能因此新值而更新此蜈。

實(shí)現(xiàn)觀察者模式的方法不止一種即横,包含 Subject 和 Observer 接口的類最為常見。

C8CE0C4C-F581-445E-B2F4-_1_105_c.jpeg

3裆赵、設(shè)計(jì)原則:

為了交互對象之間的松耦合設(shè)計(jì)而努力东囚。

松耦合的設(shè)計(jì)之所以能讓我們建立有彈性的OO系統(tǒng),能夠應(yīng)對變化战授,是因?yàn)閷ο笾g的互相依賴降到最低页藻。

因?yàn)槿魏螘r(shí)候我們都可以添加新的觀察者,因?yàn)橹黝}唯一依賴的東西是一個(gè)實(shí)現(xiàn)Observer接口的對象列表植兰。

4份帐、舉例(氣象站項(xiàng)目):

4.1 需求:

(1)該氣象站必須建立在專利申請的 WeatherData 對象上,由 WeatherData 對象負(fù)責(zé)追蹤目前的天氣狀況(溫度楣导、濕度弥鹦、氣壓)。

(2)建立一個(gè)應(yīng)用爷辙,有三種布告板(后面可能會(huì)有更多)彬坏,分別顯示目前的狀態(tài)、氣象統(tǒng)計(jì)和簡單的預(yù)報(bào)(三種不同形式的展示)膝晾。當(dāng)WeatherData 改變時(shí)栓始,三種布告板必須實(shí)時(shí)更新。

4.2 設(shè)計(jì):

008068C1-4A49-44AE-A02FFFCBDB_1_201_a.jpeg

4.3 代碼實(shí)現(xiàn):

(1)觀察者接口

/**
 * 觀察者接口
 *
 * 所有觀察者都要實(shí)現(xiàn)此接口
 */
public interface Observer {
    /**
     * 當(dāng)氣象觀察值改變時(shí)血当,主題會(huì)把這些狀態(tài)值傳給觀察者
     * @param temp
     * @param humidity
     * @param pressure
     */
    public void update(float temp, float humidity, float pressure);
}

(2)主題接口

/**
 * 主題接口
 *
 * 所有主題都要實(shí)現(xiàn)此接口
 */
public interface Subject {
    /**
     * 觀察者注冊接口
     * @param o
     */
    public void registerObserver(Observer o);

    /**
     * 觀察者刪除接口
     * @param o
     */
    public void removeObserver(Observer o);

    /**
     * 當(dāng)主題狀態(tài)改變時(shí)幻赚,通過這個(gè)方法告知所有的觀察者
     */
    public void notifyObservers();

}

(3)布告板接口

/**
 * 布告板接口
 *
 * 所有布告板要實(shí)現(xiàn)此接口
 */
public interface DisplatElement {
    /**
     * 當(dāng)布告板需要顯示時(shí),調(diào)用此方法
     */
    public void display();
}

(4)主題實(shí)現(xiàn)類 - 天氣數(shù)據(jù)

/**
 * 天氣數(shù)據(jù)
 * 
 * 主題實(shí)現(xiàn)類
 */
public class WeatherData implements Subject {
    /**
     * 記錄所有觀察者
     */
    private ArrayList observers;
    /**
     * 溫度
     */
    private float temperature;
    /**
     * 濕度
     */
    private float humidity;
    /**
     * 氣壓
     */
    private float pressure;

    public WeatherData(ArrayList observers) {
        this.observers = observers;
    }

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

    @Override
    public void removeObserver(Observer o) {
        observers.remove(o);
    }

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

    /**
     * 當(dāng)檢測到觀察值發(fā)生改變臊旭,并且達(dá)到要通知的條件時(shí)落恼,通知所有觀察者
     */
    public void measurementsChanged(){
        //TODO 檢測是否達(dá)到通知條件,比如必須是溫度等條件達(dá)到0.5的浮動(dòng)再通知觀察者

        notifyObservers();
    }

    /**
     * 當(dāng)傳感器返回測量的數(shù)據(jù)离熏,會(huì)調(diào)用此方法
     * @param temperature
     * @param humidity
     * @param pressure
     */
    public void setMeasurements(float temperature,float humidity,float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

}

(5)三個(gè)布告板實(shí)現(xiàn)類佳谦,只有現(xiàn)實(shí)的屬性不同。

public class CurrentConditionsDisplay implements Observer, DisplatElement {
    /**
     * 溫度
     */
    private float temperature;
    /**
     * 濕度
     */
    private float humidity;

    /**
     * 主題
     */
    private Subject weatherData;

    public CurrentConditionsDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("CurrentConditionsDisplay【temperature:" +  temperature + ";humidity:" + humidity+"】");
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temperature = temp;
        this.humidity = humidity;
        display();
    }
}
public class ForecastDisplay implements Observer, DisplatElement {
    /**
     * 濕度
     */
    private float humidity;
    /**
     * 氣壓
     */
    private float pressure;

    /**
     * 主題
     */
    private Subject weatherData;

    public ForecastDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("ForecastDisplay【humidity:" +  humidity + ";pressure:" + pressure+"】");
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }
}
public class StatisticsDisplay implements Observer, DisplatElement {
    /**
     * 溫度
     */
    private float temperature;

    /**
     * 氣壓
     */
    private float pressure;

    /**
     * 主題
     */
    private Subject weatherData;

    public StatisticsDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("StatisticsDisplay【temperature:" +  temperature + ";pressure:" + pressure+"】");
    }

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

(6)測試類

public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData(new ArrayList<Observer>());

        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);

        weatherData.setMeasurements(50,60,30f);
        weatherData.setMeasurements(40,50,20f);
        weatherData.setMeasurements(60,20,40f);
    }
}
0308F50D-DD12-4D3C-8FD3-BBFCFD9A7962_1_201_a.jpeg
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末滋戳,一起剝皮案震驚了整個(gè)濱河市钻蔑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奸鸯,老刑警劉巖咪笑,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異娄涩,居然都是意外死亡窗怒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扬虚,“玉大人努隙,你說我怎么就攤上這事】字幔” “怎么了剃法?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵碎捺,是天一觀的道長路鹰。 經(jīng)常有香客問我,道長收厨,這世上最難降的妖魔是什么晋柱? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮诵叁,結(jié)果婚禮上雁竞,老公的妹妹穿的比我還像新娘。我一直安慰自己拧额,他們只是感情好碑诉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著侥锦,像睡著了一般进栽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上恭垦,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天快毛,我揣著相機(jī)與錄音,去河邊找鬼番挺。 笑死唠帝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的玄柏。 我是一名探鬼主播襟衰,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼粪摘!你這毒婦竟也來了右蒲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤赶熟,失蹤者是張志新(化名)和其女友劉穎瑰妄,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體映砖,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡间坐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竹宋。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡劳澄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜈七,到底是詐尸還是另有隱情秒拔,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布飒硅,位于F島的核電站砂缩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏三娩。R本人自食惡果不足惜庵芭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雀监。 院中可真熱鬧双吆,春花似錦、人聲如沸会前。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓦宜。三九已至蔚万,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間歉提,已是汗流浹背笛坦。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苔巨,地道東北人版扩。 一個(gè)月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像侄泽,于是被迫代替她去往敵國和親礁芦。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

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