Java-观察者模式简单例子

一、自定义观察者模式

需要subject类 (一)以及Observer类(多)
subject 主要功能是接收数据以及通知变更观察者(Observer)。
observer 主要功能是接收变更后的数据,一定实现update接口。
核心:subject管理所有观察者,当数据变更时通知所用观察者(就是调用update)
subject接口类:

public interface ISubject {
    void registerObservers(IObervers oberver);//注册观察者

    void removeObservers(IObervers oberver);//删除观察者

    void notifyObservers();//变更通知
}

subject具体实现类:

public class Subject implements ISubject {

    private List obervers;
    private Weather weather;


    public Subject() {
        obervers = new ArrayList<>();
        weather = new Weather();
    }

    @Override
    public void registerObservers(IObervers oberver) {
        obervers.add(oberver);
    }

    @Override
    public void removeObservers(IObervers oberver) {
        int index = obervers.indexOf(oberver);
        if (index >= 0) {
            obervers.remove(oberver);
        }
    }

    @Override
    public void notifyObservers() {
        for (IObervers oberver : obervers) {
            oberver.update(weather);
        }
    }

    public void setNewWeatherData(double temp, double humidity) {
        weather.setHumidity(humidity);
        weather.setTemp(temp);
        notifyObservers();
    }
}

数据封装类:

public class Weather {
    private double temp;
    private double humidity;

    public double getTemp() {
        return temp;
    }

    public void setTemp(double temp) {
        this.temp = temp;
    }

    public double getHumidity() {
        return humidity;
    }

    public void setHumidity(double humidity) {
        this.humidity = humidity;
    }
}

观察者接口类:(update很关键)

public interface IObervers {
    void update(Weather weather);
}

观察者具体实现类:


public class Display implements IObervers {

    private Weather weather;

    public Display(ISubject subject) {
        subject.registerObservers(this);
    }


    public void display() {
        System.out.println("温度:" + weather.getTemp());
    }

    @Override
    public void update(Weather weather) {
        this.weather = weather;
    }

    public static void main(String[] args) {
        Subject subject = new Subject();
        Display display = new Display(subject);
        subject.setNewWeatherData(1.1, 60);
        display.display();
    }
}

上面就是简单的例子,需要创建主题,创建观察者并注册,主题数据变化,观察者显示。

二、利用Java内置观察者模式

主题类:
Observable为 java.util.Observable;,类似上面的subject,里面管理了注册,删除,更新。我们只需要在变更的时候先调用
setChanged(); 方法说明数据改变了,再调用notifyObservers(); 超类会自行更新。切记:此类要实现数据的get方法(如下getWeather()),以此来获取数据,不用想上面的传来传去。

package com.rkt.demo.observer2;

import com.rkt.demo.observers.Weather;

import java.util.Observable;

public class MySubject extends Observable {
    private Weather weather;

    public void setNewWeatherData(double temp, double humidity) {
        weather = new Weather();
        weather.setHumidity(humidity);
        weather.setTemp(temp);
        setChanged();
        notifyObservers();
    }

    public Weather getWeather() {
        return weather;
    }

}

观察者类

实现Observer 接口

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

public class MyDisplay implements Observer {
    private Weather weather = new Weather();

    public MyDisplay(Observable subject){
        subject.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof MySubject) {
            MySubject subject = (MySubject) o;
            weather = subject.getWeather();
        }
    }

    public void display() {
        System.out.println("温度:"+weather.getTemp());
    }

    public static void main(String[] args) {
        MySubject subject=new MySubject();
        MyDisplay myDisplay=new MyDisplay(subject);
        subject.setNewWeatherData(1.2, 30);
        myDisplay.display();
    }
}

可能会有一点疑问,数据改变时怎么通知的观察者;
看下超类源码,将自己直接仍回观察者,然后观察者通过主题的get方法获取数据类(这就是上面为什么一定要实现数据类的get方法)

public void notifyObservers(Object arg) {
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

你可能感兴趣的:(Java-观察者模式简单例子)