频道栏目
首页 > 程序开发 > 软件开发 > Java > 正文
JAVA观察者模式适用场景和手动实现
2017-10-10 09:19:00      个评论    来源:小呆娃的博客  
收藏   我要投稿

定义:对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

一、适用场景

1.当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

2.当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。

3.当一个对象必须通知其它对象, 而它又不能假定其它对象是谁。

二、涉及对象

1.主题接口(Subject):目标知道它的观察者。 可以有任意多个观察者观察同一个目标。提供注册和删除观察者对象的接口。

2.观察者接口(Observer):为那些在主题发生改变时需获得通知的对象定义一个更新接口

3.具体主题(ConcretSubject):将有关状态存入各ConcreteObserver 对象。当它的状态发生改变时,向它的各个观察者发出通知。

4.具体观察者(ConcretObserver):维护一个指向ConcreteSubject 对象的引用。存储有关状态, 这些状态应与目标的状态保持一致。实现 Observer 的更新接口使自身状态与目标的状态保持一致。

例子一:手动实现观察者模式

Subject类:

 public interface Subject {             
 //注册观察者    public void
    //删除观察者     public void
 removeObserver(Observer o);    
 //当主题状态改变时,调用该方法,通知所有的观察者  
 public void notifyObservers(); }

Observer类:

 public interface Observer {    
 public void update(float temp,float humidity,float pressure);  }

需求的额外接口DisplayElement:

public interface DisplayElement {
    public void display();
}

具体主题类–WeatherData

import java.util.ArrayList;
public class WeatherData implements Subject{

    private ArrayList observers;//记录观察者

    private float temperture;

    private float humidity;

    private float pressure;

    public WeatherData() {
        //在构造器中建立观察者
        observers = new ArrayList();
    }
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);

    }

    @Override
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if(i>=0)
            observers.remove(i);
    }

    @Override
    public void notifyObservers() {
        for (int i = 0; i < observers.size(); i++) {
            Observer observer = (Observer) observers.get(i);
            observer.update(temperture, humidity, pressure);
        }   
    }

    //当气象站得到更新观测值时,通知观察者
    public void measurementsChanged(){
        notifyObservers();
    }

    public void setMeasurements(float temperature,float humidity,float pressure){
        this.temperture=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        measurementsChanged();
    }
}

具体观察者CurrentConditionDisplay:

public class CurrentConditionsDislpay 
            implements Observer, DisplayElement {

    private float temperture;

    private float humidity;

    private Subject weatherData;

    public  CurrentConditionsDislpay(Subject weatherData) {
        this.weatherData=weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void update(float temperture, float humidity, float pressure) {
        this.humidity=humidity;
        this.temperture=temperture;
        display();

    }

    @Override
    public void display() {
        System.out.println("Current conditions:"+temperture+"F degrees and "+humidity+"% humidity");

    }

}

测试类TestObserver:

public class TestObserver {
    public static void main(String[] args) {
        WeatherData  weatherData = new WeatherData();
        CurrentConditionsDislpay currentDisplay = new CurrentConditionsDislpay(weatherData);
        weatherData.setMeasurements(80, 65, 30.4f);
    }
}

例子二:使用JAVA内置的支持实现

具体主题类WeatherData:

import java.util.Observable;

public class WeatherData extends Observable{

    private float temperture;

    private float humidity;

    private float pressure;

    public WeatherData() {

    }

    //当气象站得到更新观测值时,通知观察者
    public void measurementsChanged(){
        setChanged();
        notifyObservers();
    }

    public void setMeasurements(float temperature,float humidity,float pressure){
        this.temperture=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        measurementsChanged();
    }

    public float getTemperture() {
        return temperture;
    }

    public void setTemperture(float temperture) {
        this.temperture = temperture;
    }

    public float getHumidity() {
        return humidity;
    }

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

    public float getPressure() {
        return pressure;
    }

    public void setPressure(float pressure) {
        this.pressure = pressure;
    }
}

具体观察者:

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

public class CurrentConditionsDislpay implements Observer, displayElement {

    private float temperture;

    private float humidity;

    Observable observable;

    public  CurrentConditionsDislpay(Observable observable) {
        this.observable=observable;
        observable.addObserver(this);
    }

    @Override
    public void display() {
        System.out.println("Current conditions:"+temperture+"F degrees and "+humidity+"% humidity");

    }

    @Override
    public void update(Observable o, Object arg) {
        if(o instanceof WeatherData){
            WeatherData weatherData = (WeatherData) o;
            this.temperture=weatherData.getTemperture();
            this.humidity=weatherData.getHumidity();
            display();
        }
    }
}

测试类和所需要的接口DisplayElement和手动实现的相同。

三、设计原则

1.找出程序中会变化的方面,然后将其和固定不变的方面相分离。
在观察者模式中,会改变的是主题的状态,以及观察者的数目和类型。用这个模式,你可以改变依赖与主题状态的对象,却不必改变主题。这为提前规划。

2.针对接口编程,不针对实现编程
主题与观察者都使用接口,观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者,这样可以让两者之间运作正常,又同时具有松耦合的优点。

3.多组合,少继承
观察者模式利用组合将许多观察者组合进主题中,对象之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式产生的。

点击复制链接 与好友分享!回本站首页
上一篇:java日期格式化中HH与hh的区别
下一篇:最后一页
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站