理解java設計模式之觀察者模式


在生活實際中,我們經常會遇到關注一個事物數據變化的情況,例如生活中的溫度記錄儀,當溫度變化時,我們觀察它溫度變化的曲線,溫度記錄日志等。對於這一類問題,很接近java設計模式里面的“觀察者模式”,它適合解決多種對象跟蹤一個對象數據變化的程序結構問題。

觀察者設計模式涉及到兩種角色:主題(Subject)和觀察者(Observer)

下面以java JDK中已有的觀察者設計模式代碼,展示使用:

1.主題(Subject):Observable類派生出來的子類,只需要定義各被監控的數據及getter()、setter()方法,getter方法主要用於具體觀察者“拉”數據,setter方法主要用於更新、設置changed變量及通知各具體觀察者進行數據響應。代碼如下:

import java.util.Observable;

public class Subject extends Observable{
    private String data;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        //更新數據
        this.data = data;
        //置更新數據標志
        setChanged();
        //通知各個具體的觀察者,這里有推數據的作用
        notifyObservers(null);
    }
}

2.觀察者(Observer):編寫具體的觀察者類實現觀察者接口,通過參數傳遞主題對象獲取更新的數據。update()方法主要用於“拉”數據及處理過程。代碼如下:

import java.util.Observable;
import java.util.Observer;

public class ObserverOne implements Observer{

    @Override
    public void update(Observable o, Object arg) {
        // TODO Auto-generated method stub
        Subject subject = (Subject) o;
        System.out.println("數據正在更新為:"+subject.getData());
        
    }
}

下面寫一個簡單的測試類來測試一下:

import java.util.Observer;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Observer obj = new ObserverOne();
        Subject subject = new Subject();
        subject.addObserver(obj);
        subject.setData("One");
    }
}

輸出結果:“數據正在更新為:One”

由java JDK實現的觀察者模式來看,當在使用時感覺代碼很簡單,其實去看Observerable類和Observer接口的源碼就知道,這些都是專家級的代碼,學習了觀察者模式后,下面得出一些結論:

1)主題要知道哪些觀察者對其進行監測,說明主題類中一定有一個集合類成員變量,添加和刪除及判斷這些觀察者對象是否存在。

2)觀察者類一定是多態的,有共同的父類接口。

3)主題完成的功能基本是固定的,添加觀察者、撤銷觀察者、通知消息給觀察者及引起觀察者響應(即“拉”數據),可以抽象出來。

經過以上的思考和總結,下面是自定義形式寫的觀察者模式:

1.編寫觀察者接口(IObserver)。代碼如下:

public interface IObserver{
    //傳入的參數對象可以間接獲取變化后的主題數據
    public void refresh(ISubject subject);

}

2.編寫主題接口(ISubject)。代碼如下:

public interface ISubject{
    //注冊觀察者
    public void register(IObserver obs);
    //撤銷觀察者
    public void unregister(IObserver obs);
    //通知所有觀察者及進行數據響應
    public void notifyObservers();

}

3.增加主題抽象類層(AbstractSubject)。代碼如下:

import java.util.ArrayList;

public class AbstractSubject implements ISubject{
    private ArrayList<IObserver> array = new ArrayList<IObserver>();

    @Override
    public void register(IObserver obs) {
        // TODO Auto-generated method stub
        array.add(obs);
        
    }
    @Override
    public void unregister(IObserver obs) {
        // TODO Auto-generated method stub
        array.remove(obs);
        
    }
    @Override
    public void notifyObservers() {
        // TODO Auto-generated method stub
        for(int i=0;i<array.size();i++){
            IObserver  obs = array.get(i);
            obs.refresh(this);
        }    
    }
}

4.主題子類定義被監控數據(Subject)。代碼如下:

public class Subject extends AbstractSubject{
    //被監控的數據
    private String data;
    
    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }
}

5.觀察者對象(Observer)“拉”數據得到數據響應。代碼如下:

public class Observer implements IObserver {

    @Override
    public void refresh(ISubject obj) {
        // TODO Auto-generated method stub
        Subject subject = (Subject)obj;
        System.out.println("數據正在更新為:"+subject.getData());
    }
}

最后來寫一個測試類來測試一下:

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IObserver obs = new Observer();
        Subject subject = new Subject();
        subject.register(obs);
        subject.setData("one");
        subject.notifyObservers();
    }
}

輸出結果是一樣的!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM