行爲型模式:觀察者模式。

行爲型模式:觀察者模式java

燈塔

十一大行爲型模式之七:觀察者模式。設計模式

簡介

姓名 :觀察者模式
英文名 :Observer Pattern
價值觀 :盯着你怎麼着
我的介紹
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.
定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則全部依賴於它的對象都會獲得通知並被自動更新。
(來自《設計模式之禪》)微信

你要的故事

想來想去,就拿咱們如今生活中最常體會到的事情來說觀察者模式--朋友圈。小明、小紅、小東 3 人是好朋友,最近他們的父母都給安排了手機,剛用上手機那是至關的興奮呀。他們立馬從 QQ 轉投到微信的懷抱,對微信的朋友圈玩的不亦樂乎,什麼事情都往上面發。忽然有一天,小明和小紅由於一些小事爭執鬧彆扭了,緣由就是他們對一道數學題有不一樣的看法。就跟咱們小時候和朋友玩得好好的,忽然由於一點小事就鬧翻了。小紅比較孩子氣,立馬就屏蔽了小明的朋友圈,不想再看到有關小明相關的信息。故事就是這麼一回事,關注點就在這朋友圈上。朋友圈就是運用觀察者模式的一個很好的樣例。爲何這麼說?咱們發朋友圈的時候,那些沒有屏蔽咱們朋友圈的好友,會收到信息推送。也就是沒有屏蔽咱們朋友圈的好友實際上是訂閱了咱們朋友圈,好友至關於觀察者,咱們是被觀察的對象。符合觀察者模式這個關係。ide

咱們經過代碼來描述小明、小紅、小東他們在朋友圈玩的場景。利用觀察者模式,須要觀察對象和被觀察對象,因此咱們先定義 2 個接口,分別是 Observable (可被觀察接口) 和 Observer (觀察者接口)。學習

實現 Observable 接口的對象說明是可被訂閱觀察的,因此它須要 addObserver() 新增訂閱者方法和 removeObserver() 移除訂閱者方法,另外還有一個是必須的,就是通知各個訂閱者消息的方法 notifyObservers()。那 Observable 接口代碼以下所示。this

interface Observable {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(String message);
}

實現 Observer 接口的對象說明是能夠去訂閱觀察的,也就是說能夠接收被訂閱的對象發出來的消息,那就須要一個接收消息的方法 update()。代碼以下所示。設計

interface Observer {
    void update(String name, String message);
}

爲了讓你們不混淆,先把觀察者和被觀察者分離開,其實在這個例子中,觀察者和被觀察者是同一個對象 User 的。這裏就分開,分紅 UserFriend,後面會給出正確的代碼,稍安勿躁哈。這裏 User 做爲被觀察者,實現了 Observable 接口,而 Friend 做爲觀察者,實現了 Observer 接口。代碼以下。code

class User implements Observable {

    private List<Observer> friends;
    private String name;

    public User(String name) {
        this.name = name;
        this.friends = new LinkedList<>();
    }

    public void sendMessage(String message) {
        this.notifyObservers(message);
    }

    @Override
    public void addObserver(Observer observer) {
        this.friends.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        this.friends.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        this.friends.forEach(friend -> {
            friend.update(this.name, message);
        });
    }
}

class Friend implements Observer {

    private String name;

    public Friend(String name) {
        this.name = name;
    }
    @Override
    public void update(String name, String message) {
        System.out.println("【" + this.name + "】看到【" + name + "】發的朋友圈:" + message);
    }
}

public class ObserverTest {

    public static void main(String[] args) {
        User xiaoMing = new User("小明");
        Friend xiaoHong = new Friend("小紅");
        Friend xiaoDong = new Friend("小東");
        xiaoMing.addObserver(xiaoHong);
        xiaoMing.addObserver(xiaoDong);
        xiaoMing.sendMessage("今天真開心");
        // 小紅和小明鬧彆扭了,小紅取消訂閱小明的朋友圈
        xiaoMing.removeObserver(xiaoHong);
        xiaoMing.sendMessage("但願明天也像今天同樣開心");
    }

}

打印結果:
【小紅】看到【小明】發的朋友圈:今天真開心
【小東】看到【小明】發的朋友圈:今天真開心
【小東】看到【小明】發的朋友圈:但願明天也像今天同樣開心

看到代碼執行結果,小紅和小東都訂閱了小明的朋友圈,小明發了朋友圈:今天真開心。他們倆都收到了,由於小紅和小明鬧彆扭,小紅取消訂閱小明的朋友圈,因此小明後來發的朋友圈,小紅沒收到。server

上面代碼實際上是不對的,不該該用 UserFriend 2 個類來定義。若是小明訂閱小紅和小東的朋友圈呢?這樣實現比較麻煩,主要是爲了分清 觀察者被觀察者 這 2 個概念,經過上面的例子應該分清楚了 2 個概念了,那就能夠來看正確的代碼,小明、小紅、小東他們其實都是觀察者和被觀察者,因此咱們用 User2 來定義他們就能夠,User2 實現了 ObservableObserver 接口。代碼以下。對象

class User2 implements Observable, Observer {

    private List<Observer> friends;
    private String name;

    public User2(String name) {
        this.name = name;
        this.friends = new LinkedList<>();
    }

    @Override
    public void addObserver(Observer observer) {
        this.friends.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        this.friends.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        this.friends.forEach(friend -> {
            friend.update(this.name, message);
        });
    }

    @Override
    public void update(String name, String message) {
        System.out.println("【" + this.name + "】看到【" + name + "】發的朋友圈:" + message);
    }

    public void sendMessage(String message) {
        this.notifyObservers(message);
    }
}

public class ObserverTest {

    public static void main(String[] args) {
        User2 xiaoMing2 = new User2("小明");
        User2 xiaoHong2 = new User2("小紅");
        User2 xiaoDong2 = new User2("小東");
        xiaoMing2.addObserver(xiaoHong2);
        xiaoMing2.addObserver(xiaoDong2);
        xiaoMing2.sendMessage("今天真開心");
        xiaoMing2.removeObserver(xiaoHong2);
        xiaoMing2.sendMessage("但願明天也像今天同樣開心");

        xiaoHong2.addObserver(xiaoMing2);
        xiaoHong2.addObserver(xiaoDong2);
        xiaoHong2.sendMessage("今天和小明吵架了,屏蔽他的朋友圈");

        xiaoDong2.addObserver(xiaoMing2);
        xiaoDong2.addObserver(xiaoHong2);
        xiaoDong2.sendMessage("小明和小紅吵架了,夾在中間好尷尬");
    }

}

打印結果:
【小紅】看到【小明】發的朋友圈:今天真開心
【小東】看到【小明】發的朋友圈:今天真開心
【小東】看到【小明】發的朋友圈:但願明天也像今天同樣開心
【小明】看到【小紅】發的朋友圈:今天和小明吵架了,屏蔽他的朋友圈
【小東】看到【小紅】發的朋友圈:今天和小明吵架了,屏蔽他的朋友圈
【小明】看到【小東】發的朋友圈:小明和小紅吵架了,夾在中間好尷尬
【小紅】看到【小東】發的朋友圈:小明和小紅吵架了,夾在中間好尷尬

從代碼中,咱們看到小明、小紅、小東 3 我的互相訂閱朋友圈,固然中途小紅屏蔽了小明的朋友圈。這就是 觀察者被觀察者 恰好是同一個對象的實現。

總結

觀察者模式 是一個比較特殊的設計模式,它定義了觸發機制,觀察者只要訂閱了被觀察者,就能夠第一時間獲得被觀察者傳遞的信息。在工做中,使用觀察者模式的場景也比較多,好比消息隊列消費,Android 開發中的事件觸發機制等等。好,觀察者模式就到這。

推薦閱讀:

行爲型模式:迭代器模式

行爲型模式:策略模式

行爲型模式:責任鏈模式

設計模式系列文章持續更新中,歡迎關注公衆號 LieBrother,一塊兒交流學習。

相關文章
相關標籤/搜索