1. 程式人生 > >【設計模式】-09觀察者模式

【設計模式】-09觀察者模式

1.什麼是觀察者模式?

 

定義:在物件之間定義了一對多的依賴,這樣一來,當一個物件改變狀態,依賴它的物件會收到通知並自動更新.

舉個栗子: 張三和李四準備上演一場搶劫銀行的行動,張三負責搶劫,李四負責放哨,他們兩約定,如果李四這邊看到警察來就立即通知張三,張三收到通知後立馬逃跑...在上面的例子中,張三的角色其實就是觀察者,李四是被觀察者.張三觀察李四這邊的狀態,如果李四這邊的狀態發生改變(一切正常->情況不妙),張三就立即做出行動或反饋.現實中類似的還有訊息的訂閱和接收,比如微信公眾號,其模式其實也是觀察者模式.

 

2.為什麼要使用觀察者模式?

觀察者模式可以降低系統耦合度,觀察者和主體(被觀察者)完美分離,另外主體的變化可以通知到所有匹配過的觀察者,所有依賴於主體的物件都得到通知並自動重新整理。

 

3.實現

先來看一下觀察者模式的結構圖:

觀察者模式主要由觀察者(Observer),主體(Subject)構成,再具體一點就是由抽象觀察者(observer),抽象主體(subject),觀察者實現類(concreteObserver),主體實現類(concreteSuject)構成,為了讓程式碼具有更高的可擴充套件性,你還可以把主體寫成抽象類,我這了為了演示就不寫的太複雜了,感興趣的可以看看百度百科提供的觀察者模式-javaDemo,那段程式碼寫的很精彩,值得一讀.

Subject:

主體,存放所有觀察者物件,存放自身狀態,以及新增/移除觀察者的方法,通知所有觀察者的方法

/**
 * 被觀察者物件
 */
public class Subject {
    private List<Observer> observers = new ArrayList<>();
    private Integer state;

    public void attach(Observer observer) {
        observers.add(observer);
    }

    public void remove(Observer observer) {
        observers.remove(observer);
    }

    private void notifyALLObserver() {
        for (Observer observer : observers) {
            observer.update();
        }
    }

    public Integer getState() {
        return state;
    }

    public void setState(Integer state) {
        this.state = state;
        this.notifyALLObserver();
    }
}

observer:

觀察者物件,提供了update方法,以供在收到通知時及時作出反應.

/**
 * 觀察者物件
 */
public abstract class Observer {
    protected Subject subject;
    public abstract void update();
}

下面我以一個具體的例子來模擬實現觀察者模式. 現在有一對情侶,主體是丈母孃,只有在丈母孃狀態發生改變時(???)情侶才能作出具體的反饋,比如丈母孃的狀態由1變為了2(可以理解為生氣變成了高興),這個時候男生看到後會立刻去打遊戲,女生看到後則會去購物,程式碼模擬實現一下:

public class BoyObserver extends Observer {
    /**
     * 被構造時即被新增至觀察者列表裡
     */
    public BoyObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("狀態改變了,狀態值變為了:" + subject.getState() + "  我要去打遊戲了....");
    }
}


public class GirlObserver extends Observer {
    /**
     * 被構造時即被新增至觀察者列表裡
     */
    public GirlObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("狀態改變了,狀態值變為了:" + subject.getState() +"  我要去購物了....");
    }
}
/**
 * 測試客戶端
 */
public class Client {
    public static void main(String[] args) {
        Subject subject = new Subject();
        Observer girlObserver = new GirlObserver(subject);
        Observer boyObserver = new BoyObserver(subject);
        System.out.println("==========第一次===========>");
        subject.setState(1);
        System.out.println("==========第二次===========>");
        subject.setState(2);
        System.out.println("==========第三次===========>");
        subject.remove(boyObserver);
        subject.setState(3);
    }
}

執行一下測試類可以看到控制檯輸出:

第一次當主體狀態變為1時,男孩和女孩都收到了通知,於是兩人都去幹自己喜歡的事了,第二次也一樣,第三次時,丈母孃不高興讓男孩打遊戲了,覺得這樣沒出息,於是把他從列表裡踢出去了,然後他就收不到通知了...

以上便是觀察者模式的簡單實現,如果想要提高程式碼的可擴充套件性,可以把主體寫得更抽象,運用泛型和反射,讓程式碼的擴充套件性爆棚.