Java 設計模式-觀察者模式(Observer)

寫了兩個關於設計模式的筆記之後突然感覺上癮了,我的天啊,原來設計模式這麼簡單。隱隱約約覺得自己離架構師不遠了,好開心,,,

“Ruffian,Ruffian,快醒醒,怎麼博客寫一半就睡着了,,,”。臥槽,是夢,是夢,,,

好吧,被叫醒了,那還是繼續寫博客吧。

今天記錄一下觀察這模式。先看看定義

觀察這模式:對象間的一種一對多的依賴關係,一個對象的狀態發生變化時,所有依賴於它的對象都得到通知並自動刷新。

誒,這個定義不錯,簡單明瞭,看字面意思就理解的差不多了,個人覺得還是有點抽象。

嗯,那麼舉個貼切生活的例子,微信公衆號(CSDN大神鴻洋也曾使用這個來舉例說明觀察者模式,這裏不排除筆者有抄襲的嫌疑,哈哈,不過對比網上這麼多例子,還是覺得這個貼切,那就拿微信公衆號來舉例子說明 觀察者模式 吧)

在互聯網迅速發展的今天,微信這個大平臺似乎成了一些商戶宣傳和推廣自己產品的好渠道,例如深圳華強北某手機商戶,開發了一個微信公衆號,每天推送自己的新品手機,手機愛好者通過訂閱公衆號,可以接收到商戶推送的消息,當然,哪天不喜歡了,就可以取消關注。

結合定義,

對象間的一種一對多的依賴關係

微信公衆號跟關注者(手機愛好者)是一種一對多的關係

一個對象的狀態發生變化時,所有依賴於它的對象都得到通知並自動刷新

公衆號推送了一條關於新品手機的消息,(一個對象發生了變化) ,關注者(依賴它的對象)就可以接收到推送過來的消息(都得到通知並自動刷新)。

觀察者模式的定義真的很容易理解,特別結合微信公衆號這個例子,如果你這都理解不了?臥槽,這都理解不了,那就只能通過代碼來看看能不能幫到你了

首先創建一個微信公衆號抽象類(主題類),不同類型的公衆號從這裏繼承,然後各自實現自己的業務,然後創建一個觀察者接口,所有的觀察者實現這個接口。

主題類(公衆號抽象類)

package cn.design.java.observer;

import java.util.ArrayList;
import java.util.List;

/**
 * 公衆號抽象類<br/>
 * 所有公衆號繼承此類
 * 
 * @author Ruffian
 * @date 2016年5月13日
 * 
 */
public abstract class Subject {

    // 保存註冊的觀察者(保存所有關注公衆號的用戶)
    private List<Observer> observers = new ArrayList<Observer>();

    // 註冊觀察者(關注公衆號)
    public void attach(Observer observer) {
        observers.add(observer);
    }

    // 刪除觀察者(取消關注)
    public void detach(Observer observer) {
        observers.remove(observer);
    }

    // 通知所有註冊的觀察者(推送消息給用戶)
    public void nodifyObservers() {
        for (Observer observer : observers) {
            observer.update(this);
        }
    }

}

觀察者(接口)

package cn.design.java.observer;

/**
 * 觀察者接口<br/>
 * 所有觀察者實現此接口
 * 
 * @author Ruffian
 * @date 2016年5月13日
 * 
 */
public interface Observer {

    /**
     * 更新接口
     * 
     * @param msg
     * @author Ruffian
     * @date 2016年5月13日
     */
    public void update(Subject subject);

}

仔細看代碼,註釋的很詳細了。接下來我們創建一個具體主題的實現類(手機市場公衆號),創建2個觀察者具體實現類(手機愛好者),代碼只是爲了只管體現1對多的模式,不要太在意邏輯(這裏我純粹copy了一下)

具體主題的實現類(手機市場公衆號)

package cn.design.java.observer;

/**
 * 主題實現類<br/>
 * 某個手機行業相關的公衆號
 * 
 * @author Ruffian
 * @date 2016年5月13日
 * 
 */
public class PhoneSubject extends Subject {

    private double price;
    private String phone;

    // 設置推送信息(手機型號,價格)
    public void setPhoneMsg(String phone, double price) {
        this.phone = phone;
        this.price = price;
    }

    // 獲取推送信息
    public String getPhoneMsg() {
        return "手機型號:" + phone + ",價格:" + price;
    }

    // 推送內容
    public void pushPhone() {

        System.out.println("公衆號推送:" + getPhoneMsg());

        // 通知觀察者
        nodifyObservers();

    }

}

觀察者具體實現類(手機愛好者)

package cn.design.java.observer;

/**
 * 觀察者實現類<br/>
 * 手機愛好者
 * 
 * @author Ruffian
 * @date 2016年5月13日
 * 
 */
public class PhoneFans1Observer implements Observer {

    @Override
    public void update(Subject subject) {

        // 接收到公衆號推送的消息

        /**
         * update(Subject subject) <br/>
         * 備註: 參數可以設置爲具體的消息(String),或者 Subject對象<br/>
         * 1.String:直接展示推送過來的消息 <br/>
         * 2.Subject:如果是Subject對象,則從Subject對象中獲取需要的內容
         */

        String phoneMsg = ((PhoneSubject) subject).getPhoneMsg();

        // 展示消息
        System.out.println("粉絲1收到消息:" + phoneMsg);

    }

}
package cn.design.java.observer;

/**
 * 觀察者實現類<br/>
 * 手機愛好者
 * 
 * @author Ruffian
 * @date 2016年5月13日
 * 
 */
public class PhoneFans2Observer implements Observer {

    @Override
    public void update(Subject subject) {

        // 接收到公衆號推送的消息

        /**
         * update(Subject subject) <br/>
         * 備註: 參數可以設置爲具體的消息(String),或者 Subject對象<br/>
         * 1.String:直接展示推送過來的消息 <br/>
         * 2.Subject:如果是Subject對象,則從Subject對象中獲取需要的內容
         */

        String phoneMsg = ((PhoneSubject) subject).getPhoneMsg();

        // 展示消息
        System.out.println("粉絲2收到消息:" + phoneMsg);

    }

}

訂閱者實現類創建了2個,公衆號創建了1個,現在兩個訂閱者去訂閱公衆號,那麼當公衆號推送手機新品的時候,所有的訂閱者都能接收到來自公衆號的推送消息。

測試類

package cn.design.java.observer;

public class Test {
    public static void main(String[] args) {

        PhoneSubject subject = new PhoneSubject();
        Observer phoneFans1 = new PhoneFans1Observer();
        Observer phoneFans2 = new PhoneFans2Observer();

        // 手機愛好者關注公衆號
        subject.attach(phoneFans1);
        subject.attach(phoneFans2);

        // 公衆號編輯要推送的消息
        subject.setPhoneMsg("iPhone6s", 5288);
        // 推送消息
        subject.pushPhone();

    }
}

結果打印

輸出結果

臥槽,這麼簡單明瞭的例子,要說的話在代碼註釋了都寫完了,真不知道還能說些啥。看看代碼吧。

看到這裏Android開發者們有沒有想到這個模式在安卓中哪裏有用到呢?哎呀職業病,總是會想在Android哪裏有運用。想到了嗎?

沒錯就是廣播!系統某個廣播(例如手機開機啓動廣播),所有的APP都能註冊廣播接收器,來接受手機系統發出來的消息。

源碼下載

發佈了30 篇原創文章 · 獲贊 90 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章