Java設計模式-觀察者模式

DH鑌發表於2019-01-19

概念

觀察者模式:定義了物件之間的一對多依賴,這樣一來,當一個物件狀態改變時,他的所有依賴者都會收到通知並自動更新。

圖片描述

觀察者模式涉及的角色

主題(Subject):一對多中的一,持有資料,當資料更新時,通知已註冊的觀察者

觀察者(Observer):一對多中的多,接收主題資料做出響應

舉個例子

一位媽媽(主題)有兩個孩子,取名為小愛和小冰(觀察者)。一天小愛和小冰都去找她們的朋友玩,當到了吃飯的時間,媽媽總會打電話通知她們回來吃飯(孩子預設在媽媽那註冊為觀察者registerObserver),但中途小冰打電話和媽媽說:“不回來吃飯了,和朋友吃”(取消觀察者這角色removeObserver)。所以最後,只有小冰收到媽媽的通知,並告訴她今天買了你喜歡吃的雞腿(notifyObserver)。

程式碼

Person.java,Mother和Child都繼承這個類[這步和講述觀察者模式沒什麼關係]

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Mother.java

public class Mother extends Person implements Subject{

    /**
     * 她要通知的孩子
     */
    private ArrayList<Observer> children = new ArrayList<>();
    /**
     * 通知的內容
     */
    private String message;

    public Mother(String name) {
        super(name);
    }


    @Override
    public void registerObserver(Observer observer) {
        children.add(observer);
    }

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

    @Override
    public void notifyObserver() {
        children.forEach(observer -> observer.message(message));
    }

    public void sendMessage(String message) {
        this.message = message;
        // 通知她們
        notifyObserver();
    }
}

Child.java

public class Child extends Person implements Observer{

    public Child(String name) {
        super(name);
    }

    @Override
    public void message(String m) {
        System.out.println(getName() + "收到的訊息:"  + m);
    }
}

Main.java

public class Main {

    public static void main(String[] args) {
        Mother mother = new Mother("媽媽");
        Child xiaoBing = new Child("小冰");
        Child xiaoAi = new Child("小愛");

        // 孩子都是親生的,吃飯時叫她們
        mother.registerObserver(xiaoBing);
        mother.registerObserver(xiaoAi);

        mother.sendMessage("飯煮好了,回來吃飯,買了你們想吃的雞腿");

        System.out.println("------------------分割線-----------------------");
        // 小愛說不回來吃了,取消通知她
        mother.removeObserver(xiaoAi);
        mother.sendMessage("飯煮好了,回來吃飯,買了你們想吃的雞腿");
    }
}

執行結果:

小冰收到的訊息:飯煮好了,回來吃飯,買了你們想吃的雞腿
小愛收到的訊息:飯煮好了,回來吃飯,買了你們想吃的雞腿
------------------分割線-----------------------
小冰收到的訊息:飯煮好了,回來吃飯,買了你們想吃的雞腿

優點

主題觀察者之間鬆耦合。有新型別的觀察者出現時,主題的程式碼不需要修改。假如我們有一個新的具體類需要當觀察者,我們不需要為了相容新型別而修改主題的程式碼,所有要做的就是在新的類裡實現此觀察者介面,然後註冊成觀察者即可。

就好比如上面例子,如果國家不久的將來開放三胎政策,媽媽又生了個小娜,媽媽不需要修改自身的邏輯。如果孩子要回家吃飯就實現Observer介面,媽媽那registerObserver就OK。

相關文章