觀察者模式

觀察者模式定義:

Define a one-to-many dependency between objects so that when one object changes state, all its dependency are notified and updated automatically.

翻譯過來就是,定義一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新。

觀察者模式也叫做發佈訂閱模式。


場景分析:

其實這種場景在我們生活中非常常見,不知你住沒注意,媽媽把飯菜做好了,然後挨個通知你爸爸和你。

我們分析一下這個場景

有三個對象: 爸爸、 媽媽和兒子。其中 媽媽做飯,做好了之後通知爸爸和兒子。

首先,創建Mum對象 他有兩個方法做飯cooking()和通知其他人notifyOthers()。

/**
 * Created by dushangkui on 2017/3/22.
 */
public class Mum {
    private Dad dad;
    private Son son;

    public Mum(Dad dad, Son son) {
        this.dad = dad;
        this.son = son;
    }

    public static void main(String[] args) {
        Dad dad = new Dad();
        Son son = new Son();
        Mum mum = new Mum(dad,son);
        mum.cooking();
        mum.notifyOthers();
    }


    private void cooking(){
        System.out.println("開始做飯");
        System.out.println("做飯結束");
    }

    private void notifyOthers(){
        System.out.println("通知其他人吃飯");
        dad.onRecive();
        son.onRecive();
    }
}
媽媽持有爸爸和兒子的引用,好通知他們。

爸爸和兒子都要有一個方法去接收這個消息並且做出反應。

/**
 * Created by dushangkui on 2017/3/22.
 */
public class Dad {
    public void onRecive(){
        System.out.println("爸爸聽到了,正在過去");
    }
}

/**
 * Created by dushangkui on 2017/3/22.
 */
public class Son {
    public void onRecive(){        System.out.println("兒子聽到了,但是不想吃飯");    }}
運行場景:

開始做飯
做飯結束
通知其他人吃飯
爸爸聽到了,正在過去
兒子聽到了,但是不想吃飯

好了,我們忠實的完成了之前的定義,一對多關係,媽媽狀態改變了通知爸爸和兒子然後做出變化。但是這個代碼真的好爛。爲什麼說爛呢,不能擁抱變化。如果家庭有好多成員呢,誰中午不想吃飯,誰要吃飯,飯做多了就要剩下,少了就不夠吃。現在我們變一下:

先定義一個家庭成員的接口,可以接收消息:

public interface Member {
    void onRecive(String msg);
}

然後改造爸爸和兒子的類結構,實現Member接口:

public class Dad implements Member {

    @Override
    public void onRecive(String msg) {
        System.out.println("爸爸聽到了消息【" + msg + "】,正在過去");
    }
}

public class Son implements Member {

    @Override
    public void onRecive(String msg) {
        System.out.println("兒子聽到了消息【" + msg + "】,但是不想過去");
    }
}
媽媽也要與時俱進

public class Mum implements Member {
    private List<Member> familyMember = new ArrayList<Member>();

    public void eating(Member member){
        familyMember.add(member);
    }

    public static void main(String[] args) {
        Dad dad = new Dad();
        Son son = new Son();
        Mum mum = new Mum();
        //提前打報告 要不要吃飯? 爸爸要吃飯 兒子不要吃飯
        mum.eating(dad);
        mum.eating(mum);
        mum.cooking();
        mum.notifyOthers();
    }


    private void cooking(){
        System.out.println("開始做飯");
        System.out.println("做"+familyMember.size()+"個人的飯。");

        System.out.println("做飯結束");
    }

    private void notifyOthers(){
        System.out.println("通知其他人吃飯");
        for(Member member : familyMember){
            member.onRecive("飯做好了");
        }
    }

    @Override
    public void onRecive(String msg) {
        System.out.println("媽媽也要吃飯啊^.^");
    }
}

嘗試下:

開始做飯
做2個人的飯。
做飯結束
通知其他人吃飯
爸爸聽到了消息【飯做好了】,正在過去
媽媽也要吃飯啊^.^

現在如果多了其他人也能夠很好適應,如果兒子想吃飯了 直接想媽媽報告 調用eating方法就好了。提前說 好處多。


從上面我們可以總結出來 ,其實對象分兩類:消息的生產者 和消息的消費者










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