設計模式之觀察者模式

大雄45發表於2020-09-20

前言

Observer本來的意思是“觀察者”,但是實際上Observer角色並非主動的去觀察,而是被動的接收來自觀察物件角色的通知,因此,Observer也被成為Publish-Subscribe(釋出-訂閱)模式。它定義了一種一對多的依賴關係,讓多個觀察者物件同時監聽某一個主題物件。這個主題物件在狀態上發生變化時,會通知所有觀察者物件,使它們能夠自動更新自己。對於觀察者模式應用的也很多,例如大家最熟悉的MVC框架就是觀察者模式的典型應用,訊息推送,事件監聽等都是觀察者模式的最好詮釋。

在圖解設計模式中是通過一個觀察者觀察一個會生成數值的物件,並將生成的數值通過不同的觀察者顯示出來。照例通過如下UML類圖簡單熟知下流程。

設計模式之觀察者模式
這裡寫圖片描述

觀察者Observer

Observer角色負責接收來自觀察者物件角色的狀態變化的通知,它表示“觀察者”,具體的觀察者會實現該介面,用於生成數字的觀察物件角色類NumberGenerator類會呼叫update方法並且將生成的數字變化的通知傳送給Observer。

public interface Observer {
    public abstract void update(NumberGenerator generator);
}複製程式碼

觀察物件NumberGenerator

該類是用於生成數值的抽象類,提供了獲取數值和生成數值的抽象方法,需要子類去實現。並且提供了一個存放觀察數值變化的觀察者物件的List。方法addObserver(Observer observer)和deleteObserver(Observer observer)用註冊觀察者和刪除觀察者,重要的一步就是當有資料變化時呼叫notifyObservers方法通知所有觀察者。

public abstract class NumberGenerator {
    private ArrayList observers=new ArrayList();
    public void addObserver(Observer observer){
        observers.add(observer);
    }
    public void deleteObserver(Observer observer){
        observers.remove(observer);
    }
    public void notifyObservers(){
        Iterator iterator=observers.iterator();
        while (iterator.hasNext()){
            Observer observer= (Observer) iterator.next();
            observer.update(this);
        }
    }
    public abstract int getNumber();
    public abstract void execute();
}複製程式碼

具體的觀察物件RandomNumberGenerator

對於該具體觀察者物件,它主要是用來生成隨機數,並通過notifiObservers方法把每一次生成的結果通知給所有已註冊的觀察者

public class RandomNumberGenerator extends NumberGenerator {
    private Random random = new Random();
    private int number;

    @Override
    public int getNumber() {
        return number;
    }

    @Override
    public void execute() {
        for (int i = 0; i < 5; i++){
            number=random.nextInt(30);
            notifyObservers();
        }
    }
}複製程式碼

具體觀察者

具體觀察者實現了觀察者Observer介面,當update方法被呼叫時會去獲取要觀察的物件的最新資料,在此寫了兩個具體的觀察者。

public class DigitObserver implements Observer{
    @Override
    public void update(NumberGenerator generator) {
        System.out.println("DigitObserver:"+generator.getNumber());
    }
}

public class GraphObserver implements Observer{
    @Override
    public void update(NumberGenerator generator) {
        System.out.println("GraphObserver:"+generator.getNumber());
    }
}複製程式碼

測試類

public class Main {
    public static void main(String[] args) {
        NumberGenerator generator=new RandomNumberGenerator();
        Observer observer1=new DigitObserver();
        Observer observer2=new GraphObserver();
        generator.addObserver(observer1);
        generator.addObserver(observer2);
        generator.execute();
    }
}複製程式碼

輸出資訊:

DigitObserver:2
GraphObserver:2
DigitObserver:19
GraphObserver:19
DigitObserver:26
GraphObserver:26
DigitObserver:10
GraphObserver:10
DigitObserver:14
GraphObserver:14複製程式碼

通過上面測試程式碼,你應該發現對於觀察者物件可以有多個觀察者對其作出響應,如某些訂閱專欄,它可以被很多人訂閱,當專欄有內容更新時,它會給每一個人傳送推送,我們在訂閱專欄後,並不需要我們一直去等待它的內容更新,而不能去做自己的事情。

好了,今天的觀察者模式到此結束。有問題歡迎留言指出,Have a wonderful day .

如需文章中所寫程式碼,請移步GitHub檢視

相關文章