觀察者模式(Observer Pattern)

觀察者模式(Observer Pattern)

觀察者模式(Observer Pattern)也叫發佈訂閱模式(Publish/subscribe),它是一個在項目中經常 的模式,其定義如下:
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. (定義對象間一種“一對多”的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新)
觀察者的通用類圖

  • Subject 被觀察者
    定義被觀察者必須實現的職責,它必須能夠動態地增加、取消觀察者。它一般是抽象類或者是實現類,僅僅完成作爲被觀察者必須實現的職責:管理觀察者並通知觀察者。
  • Observer觀察者
    觀察者接收到消息後,即進行update(更新方法)操作,對接收到的信息進行處理。
  • ConcreteSubject具體的被觀察者
    定義被觀察者自己的業務,同時定義對哪些事件行通知。
  • ConcreteObserver具體的觀察者
    每個觀察者在接收到消息後的處理反應是不同的,各個觀察者有自己的處理邏輯。

觀察者模式的優點
1. 觀察者和被觀察者之間是抽象耦合
如何設計,則不 管是增加觀察者還是被觀察者都非常容易,而且在Java中都已經被蓋同的層級的定義,在系統方面更是得心應手。
2. 建立一套觸發機制
根據單一職責原則,每個類的職責是單一的,那麼怎麼把這個單一的串聯成真實世界的複雜邏輯關係呢?比如我們去打獵,打死了一隻母鹿,母鹿有三個幼崽,因後援會以了母鹿而餓死,繼而……然後……這就是一個觸發機制,形成了一個觸發鏈。觀察者模式可以完美實現這裏的鏈條形式。

觀察者模式的缺點
觀察者模式需要考慮一下開發效率和運行效率量,一個空間站以者,多個觀察者,開發和高度就會比較複雜,而且Java中消息的通知默認是順序執行,一個觀察者卡殼,會影響整體的執行效率。在這種情況下,一般考慮採用異步的方式。
多級觸發時的效率更是讓人擔憂,大家在設計時注意考慮。

觀察者模式的使用場景
1. 關聯行爲場景。需要注意的是,關聯行爲是可拆分的,而不是“組合”關係。
2. 事件多級觸發場景。
3. 跨系統的消息交換場景,如消息隊列的處理機制。


Subject類

package patterns.Observer.useUtil;

import java.util.Observable;

public class 信息暴露狂 extends Observable {
    private int 道德 = 50;
    private int 智商 = 50;
    private int 體重 = 50;

    public 信息暴露狂() {
        System.out.println("我是暴露狂,我做什麼事都要讓別人知道!!!");
    }

    @Override
    public String toString() {
        return "目前此人 道德"+道德+" 智商"+智商+" 體重"+體重;
    }

    public void 吃() {
        System.out.println("我吃");
        體重++;

        setChanged();       //此處不調不觸發下一句事件!!!!特別注意!!!
        this.notifyObservers("各種美拍高大上");
    }

    public void 喝() {
        System.out.println("我喝");
        體重++;

        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public void 拉() {
        System.out.println("我拉");
        體重--;
        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public void 撒() {
        System.out.println("我撒");
        體重--;
        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public void 睡() {
        System.out.println("我睡");

        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public void 坑() {
        System.out.println("我坑");
        道德--;

        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public void 蒙() {
        System.out.println("我蒙");
        智商--;

        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public void 拐() {
        System.out.println("我拐");
        體重--;
        道德--;

        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public void 騙() {
        System.out.println("我騙");
        智商++;
        道德--;

        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public void 偷() {
        System.out.println("我偷");
        體重--;
        道德--;

        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public void 學習() {
        System.out.println("我學習");
        智商++;
        道德++;

        setChanged();
        this.notifyObservers("各種美拍高大上");
    }

    public int get道德() {
        return 道德;
    }

    public int get智商() {
        return 智商;
    }

    public int get體重() {
        return 體重;
    }

}

Main

package patterns.Observer.useUtil;

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

public class Client {
    //觀察者模式執行場景
    public static void main(String[] args) {

        Observer 朋友圈 = new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                //處理傳來的值
                if(o instanceof 信息暴露狂){
                    信息暴露狂 human = (信息暴露狂)o;
                    //“拉”信息
                    int 道德 = 10*human.get道德();
                    int 智商 = 10*human.get智商();
                    int 體重 = 10*human.get體重();

                    String after = arg+"加道德"+道德+"、加智商"+智商+"、加體重"+體重+"=====";
                    System.out.println("發到【朋友圈】:"+after+" - "+o);
                }
            }
        };

        Observer 微博 = new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                //“推”信息
                System.out.println("發到【微博】:"+arg+" - "+o);
            }
        };

        信息暴露狂  老陳頭 = new 信息暴露狂();
        老陳頭.addObserver(朋友圈);
        老陳頭.吃();
        老陳頭.喝();
        老陳頭.addObserver(微博);    //拉巴巴的時候註冊了微博
        老陳頭.拉();
        老陳頭.撒();
        老陳頭.睡();
        老陳頭.坑();
        老陳頭.deleteObserver(朋友圈);    //不再玩朋友圈了
        老陳頭.蒙();
        老陳頭.拐();
        老陳頭.騙();
        老陳頭.偷();
        老陳頭.學習();
    }
}

運行結果

我是暴露狂,我做什麼事都要讓別人知道!!!
我吃
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重510===== - 目前此人 道德50 智商50 體重51
我喝
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重520===== - 目前此人 道德50 智商50 體重52
我拉
發到【微博】:各種美拍高大上 - 目前此人 道德50 智商50 體重51
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重510===== - 目前此人 道德50 智商50 體重51
我撒
發到【微博】:各種美拍高大上 - 目前此人 道德50 智商50 體重50
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重500===== - 目前此人 道德50 智商50 體重50
我睡
發到【微博】:各種美拍高大上 - 目前此人 道德50 智商50 體重50
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重500===== - 目前此人 道德50 智商50 體重50
我坑
發到【微博】:各種美拍高大上 - 目前此人 道德49 智商50 體重50
發到【朋友圈】:各種美拍高大上加道德490、加智商500、加體重500===== - 目前此人 道德49 智商50 體重50
我蒙
發到【微博】:各種美拍高大上 - 目前此人 道德49 智商49 體重50
我拐
發到【微博】:各種美拍高大上 - 目前此人 道德48 智商49 體重49
我騙
發到【微博】:各種美拍高大上 - 目前此人 道德47 智商50 體重49
我偷
發到【微博】:各種美拍高大上 - 目前此人 道德46 智商50 體重48
我學習
發到【微博】:各種美拍高大上 - 目前此人 道德47 智商51 體重48

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章