輕鬆學會觀察者模式

觀察者模式

當對象間存在一對多關係時,則使用觀察者模式(Observer Pattern)。好比,當一個對象被修改時,則會自動通知它的依賴對象。觀察者模式屬於行爲型模式。ide

介紹

意圖:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新。code

主要解決:一個對象狀態改變給其餘對象通知的問題,並且要考慮到易用和低耦合,保證高度的協做。server

什麼時候使用:一個對象(目標對象)的狀態發生改變,全部的依賴對象(觀察者對象)都將獲得通知,進行廣播通知。對象

如何解決:使用面向對象技術,能夠將這種依賴關係弱化。接口

應用實例:1.拍賣的時候,拍賣師觀察最高標價,而後通知給其餘競價者競價。
2.打團時每一個職業作不一樣的事情。class

優勢: 一、觀察者和被觀察者是抽象耦合的。 二、創建一套觸發機制。List

缺點: 一、若是一個被觀察者對象有不少的直接和間接的觀察者的話,將全部的觀察者都通知到會花費不少時間。 二、若是在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能致使系統崩潰。 三、觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。循環

簡單的說就是:多個對象去觀察一個對象是否發出號令(消息),而後作出相應響應動做

以DNF打團爲例子:
當團長發出攻堅開始的消息時全部的隊友開始輸出。程序

建立一個職業的抽象類(觀察者接口):Hero技術

public abstract class Hero {

    /**
     * 打團
     * @param msg
     */
    public abstract void datuan(String msg);

}
分別建立三個職業(觀察者)

建立一個紅眼:Hongyan

public class Hongyan extends Hero {

    private static final String ROLE = "帝血弒天";

    @Override
    public void datuan(String msg) {
        System.out.println(msg+ ROLE +":血魔:弒天! ");
    }
}

建立一個奶爸:Naiba

public class Naiba extends Hero {

    private static final String ROLE = "神思者";

    @Override
    public void datuan(String msg) {
        System.out.println(msg + ROLE + ": 阿波克列!");
    }
}

建立一個籃拳:Lanquan

public class Lanquan extends Hero {

    private static final String ROLE = "正義仲裁者";

    @Override
    public void datuan(String msg) {
        System.out.println(msg+ ROLE + ":粉碎吧!");
    }
}

建立一個團長(被觀察者):Captain

public class Captain {

    private List<Hero> heroes = new ArrayList<>();

    public void setMsg(String msg) {
        notifyAll(msg);
    }
    //訂閱
    public void addTeam(Hero hero) {
        heroes.add(hero);
    }
    //通知全部訂閱的觀察者
    private void notifyAll(String msg) {
        for (Hero observer : heroes) {
            observer.datuan(msg);
        }
    }


}

主程序:Main

public class Main {

    public static void main(String[] args) {
        Lanquan lanquan = new Lanquan();
        Hongyan hongyan = new Hongyan();
        Naiba naiba = new Naiba();

        Captain captain = new Captain();
        captain.addTeam(lanquan);
        captain.addTeam(hongyan);
        captain.addTeam(naiba);
        captain.setMsg("超時空攻堅戰開始-");

    }

}

執行結果:

超時空攻堅戰開始-正義仲裁者:粉碎吧!
超時空攻堅戰開始-帝血弒天:血魔:弒天! 
超時空攻堅戰開始-神思者: 阿波克列!
相關文章
相關標籤/搜索