Java設計模式之觀察者模式詳解

觀察者模式,是一對多的關係,一個主題對應多個觀察者,當這個主題發生變化的時候,全部觀察着這個主題的觀察者都會接收到通知來獲悉主題的變化。

在現實中咱們也會遇到許許多多應用觀察者模式的行爲,好比電視的節目頻道里有時候會有暴雨天氣的標誌,這個標誌是會隨着天氣的變化來顯示,而咱們顯示的也是最新的天氣標誌,在這裏電視頻道就至關因而一個主題,而咱們的電視機就是這個主題觀察者,因此當這個天氣標誌有變化時電視上的畫面也隨着變化。這就是使用的觀察者模式,下面就讓咱們用代碼實現觀察者模式。ide


首先咱們須要定義主題的接口,這裏面有三個方法,registerObserver、removeObserver和notifyObserver,分別是用來添加觀察者、去除觀察者和通知全部觀察者。其中dataChange方法是隻要當數據有變化就會被調用,咱們須要在這個方法裏調用notifyObserver去通知全部的觀察者數據變化的內容,這裏咱們使用setSimulateDataChange方法來模擬數據的變化。測試

public interface Subject {

    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObserver();
}

而後咱們建立一個具體的主題類來實現這個主題接口,假設這個類是獲取電視頻道的信息。在這個類裏面咱們須要建立一個集合用來存取觀察這個主題的全部觀察者,接口中的registerObserver和removeObserver方法實際就是對集合的增刪操做,而notifyObserver方法其實就是遍歷集合通知全部的對象。this

public class TelevisionData implements Subject {
    private String showName;
    private String showType;
    private ArrayList<Observer> list;

    public TelevisionData(){
        list = new ArrayList<Observer>();
    }

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

    @Override
    public void removeObserver(Observer observer) {
        int index = list.indexOf(observer);
        if (index>=0){
            list.remove(index);
        }
    }

    @Override
    public void notifyObserver() {
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
        Observer observer = (Observer)listIterator.next();
            observer.update(showName,showType);
        }
    }

    public void dataChange(){
        notifyObserver();
    }

    //此方法用於模擬控制數據的更新,數據更新後會調用dataChange方法
    public void setSimulateDataChange(String showName,String showType){
         this.showName = showName;
         this.showType= showType;
         dataChange();
    }
}

主題部分的代碼寫好了,接着咱們須要寫觀察者的代碼,電視節目都播放在電視上,那咱們把建立的電視類抽取出一個show方法放在Display接口中。code

public interface Display {
    void show();
}

另外觀察者還有一個共性,就是要接收更新到的數據進行更新,因此咱們再抽取出一個update方法放到Obeserver接口中。視頻

public interface Observer {
    void update(String showName,String showNum);
}

最後咱們建立觀察者的類來實現這兩個接口,在這個類中showName和showType字段是用來接收主題的數據的,而subject則是要關注的主題類型引用,經過這個引用咱們就能夠調用registerObserver和removeObserver來控制觀察者是否還要觀察這個主題。當主題更新時則會調用update方法,觀察者獲取到更新的數據就再調用show方法顯示出來。server

public class John implements Observer,Display {
    private Subject subject;
    private String showName;
    private String showType;

    public John(Subject subject){
        this.subject = subject;
    }

    @Override
    public void show() {
        System.out.println("john收看的當前天氣類型-" + showType);
        System.out.println("john收看的當前天氣級別-" + showName);
    }

    @Override
    public void update(String showName,String showType) {
        this.showName = showName;
        this.showType = showType;
        show();
    }

    public void registerObserver(){
        this.subject.registerObserver(this);
    }


    public void removeObserver(){
        this.subject.removeObserver(this);
    }
}

public class Jack implements Observer,Display {
    private Subject subject;
    private String showName;
    private String showType;

    public Jack(Subject subject){
        this.subject = subject;
    }

    @Override
    public void show() {
        System.out.println("jack收看的當前天氣類型-" + showType);
        System.out.println("jack收看的當前天氣級別-" + showName);
    }

    @Override
    public void update(String showName,String showType) {
        this.showName = showName;
        this.showType = showType;
        show();
    }

    public void registerObserver(){
        this.subject.registerObserver(this);
    }


    public void removeObserver(){
        this.subject.removeObserver(this);
    }

}

下面咱們來測試一下對象

//建立一個主題
televisionData = new TelevisionData();
    
//添加觀察者
John john = new John(televisionData);
john.registerObserver();
Jack jack = new Jack(televisionData);
jack.registerObserver();
        
//模擬數據更新
changeData("大風", "5級");
changeData("暴雨", "紅色");
    
public static void changeData(String showName, String showType) {
    televisionData.setSimulateDataChange(showName,showType);
}

結果:
john收看的當前天氣類型-紅色
john收看的當前天氣級別-暴雨
jack收看的當前天氣類型-紅色
jack收看的當前天氣級別-暴雨
john收看的當前天氣類型-5級
john收看的當前天氣級別-大風
jack收看的當前天氣類型-5級
jack收看的當前天氣級別-大風接口


咱們再試着去掉一個觀察者看它還會不會收到更新,結果是不會收到更新了rem

changeData("暴雨", "紅色");
john.removeObserver();
changeData("大風", "5級");

結果:
john收看的當前天氣類型-紅色
john收看的當前天氣級別-暴雨
jack收看的當前天氣類型-紅色
jack收看的當前天氣級別-暴雨
jack收看的當前天氣類型-5級
jack收看的當前天氣級別-大風io


總結:觀察者模式的大體原理其實就是觀察者持有主題的引用來控制主題內部的集合對本身增刪從而控制是否關注這個主題,而主題則經過對集合中的對象的操做,把數據的更新通知給全部的觀察者。

相關文章
相關標籤/搜索