设计模式观察者模式

Posted torjan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式观察者模式相关的知识,希望对你有一定的参考价值。

观察者模式 定义了对象之间的一对多的依赖,这样一来,当一个对象状态改变时,他的

多有依赖都会受到通知并自动更新。

本例为一个温度基站,和三个终端。温度基站为广播类WeatherData,三个终端监听者类分别为:TVDispaly,FactoryDisplay,MobileDisplay

其中,Observable为广播类父类,含有基本的方法。

Observer类为监听者接口,监听者需实现updata方法。

Display为显示接口,需实现display方法。

ObserverDemo为测试类。

下面直接上代码,注释很清晰。基本上很容易理解。

Observable.java

package observer;
/*
 * @author trojan
 * 广播类的父类
 * 
 */
public class Observable {
    protected boolean change = false;
    
    public void setChanged() {
        change = true;
    }
    
    public void notifyObservers(Object arg) {}
    public void notifyObservers(){ notifyObservers(null);}
    public void addObserver(Observer observer){}
}

WeatherData.java

package observer;
/*
 * @author trojan
 * 该类为广播类
 */
import java.util.ArrayList;

public class WeatherData extends Observable {
    //温度
    private float temperature;
    //湿度
    private float humidity;
    //污染指数
    private float pollution_index;
    ArrayList<Observer> observers = new ArrayList<Observer>();
    
    public WeatherData(){ }
    
    //增加监听者
    public void addObserver(Observer observer){
        observers.add(observer);
    }
    
    //将更改广播给所有监听者
    public void notifyObservers(Object arg) {
        if(change){
            for(Observer observer : observers){
                observer.update(this,arg);
            }
        }
        change = false;
    }
    
    public void notifyObservers() { notifyObservers(null);}
    
    public void stateChange() {
        //调用notifyObservers之前应调用状态改变标志函数
        setChanged();
        notifyObservers();
    }
    
    //设置状态后,将调用stateChange函数,通知监听者
    public void setState(float temperature, float humidity, float pollution_index) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pollution_index = pollution_index;
        stateChange();
    }
    
    
    public float getTemperature() {
        return temperature;
    }
    public void setTemperature(float temperature) {
        this.temperature = temperature;
    }
    public float getHumidity() {
        return humidity;
    }
    public void setHumidity(float humidity) {
        this.humidity = humidity;
    }
    public float getPollution_index() {
        return pollution_index;
    }
    public void setPollution_index(float pollution_index) {
        this.pollution_index = pollution_index;
    }
    
    
}

Display.java

package observer;
/*
 * @author
 * 显示接口
 */
public interface Display {
    public void display();
}

Observer.java

package observer;
/*
 * @author trojan
 * 这是一个监听者的接口,需要实现updata方法
 * 该方法可以被广播者调用,向监听者广播数据,或者说是一种推的方式
 * 监听者可以可以调用该方法主动更新数据,就像是一种拉的方式
 * 当然,对于每一个实现的监听者可能会有不同的数据需求
 * 所以,他们可以实现对自己感兴趣的那部分数据更新
 * 
 */
public interface Observer {
    public void update(Object obj,Object arg);;
}

TVDisplay.java

package observer;
/*
 * @author trojan
 * 对于电视台来说可能需要的气象数据要比其他的设备多
 * 所以updata需要更新更多的数据
 */
public class TVDisplay implements Observer, Display{
    Observable observable;
    private float temperature;
    private float humidity;
    private float pollution_index; 
    
    //变成一个监听者
    public void becomeOberser(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);;
    }

    @Override
    public void update(Object obj, Object arg) {
        if(obj instanceof WeatherData){
            WeatherData weatherData = (WeatherData)obj;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHumidity();
            this.pollution_index = weatherData.getPollution_index();
        }
        
    }
    
    @Override
    public void display() {
        System.out.println("WeatherData:\n"
                + "temperature: "+temperature +"\n"
                +"humidity"+humidity+"\n"
                +"pollution_index:"+pollution_index);
            
    }


}

FactoryDisplay.java

package observer;
/*
 * @author torjan
 * 工厂显示平台所需要的广播数据
 * 
 */
public class FactoryDisplay implements Observer, Display{

    Observable observable;
    private float temperature;
    private float pollution_index; 
    
    //变成一个监听者
    public void becomeOberser(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);;
    }

    @Override
    public void update(Object obj, Object arg) {
        if(obj instanceof WeatherData){
            WeatherData weatherData = (WeatherData)obj;
            this.temperature = weatherData.getTemperature();
            this.pollution_index = weatherData.getPollution_index();
        }
        
    }

    @Override
    public void display() {
        System.out.println("WeatherData:\n"
                + "temperature: "+temperature +"\n"
                +"pollution_index"+pollution_index);
        
        
    }

}

MobileDisplay.java

package observer;
/*
 * @author
 * 手机平台所需要的广播数据
 * 
 */
public class MobileDisplay implements Observer, Display {

    Observable observable;
    private float temperature;
    private float humidity;
    
    //变成一个监听者
    public void becomeOberser(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);;
    }

    @Override
    public void update(Object obj, Object arg) {
        if(obj instanceof WeatherData){
            WeatherData weatherData = (WeatherData)obj;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHumidity();
        }
        
    }
    
    @Override
    public void display() {
        System.out.println("WeatherData:\n"
                + "temperature: "+temperature +"\n"
                +"humidity"+humidity);
            
    }


}

测试类:

ObserverDemo.java

package observer;

public class ObserverDemo {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        FactoryDisplay factoryDisplay = new FactoryDisplay();
        MobileDisplay mobileDisplay = new MobileDisplay();
        TVDisplay tvDisplay = new TVDisplay();
        
        weatherData.addObserver(factoryDisplay);
        weatherData.addObserver(mobileDisplay);;
        tvDisplay.becomeOberser(weatherData);
        
        weatherData.setState(23, 70, 120);
        
        factoryDisplay.display();
        mobileDisplay.display();
        tvDisplay.display();
    }
}

测试结果:

WeatherData:
temperature: 23.0
pollution_index120.0
WeatherData:
temperature: 23.0
humidity70.0
WeatherData:
temperature: 23.0
humidity70.0
pollution_index:120.0

总结:

设计原则:找出程序中会变化的方面,然后根据其和固定不变的方面相分离

在观察者模式中,会改变的是主题的状态,以及观察者的数目和种类。用这个模式,可以改变依赖于主题状态的对象,却不必改变主题。

设计原则:针对接口编程,不针对实现编程

设计原则:多用组合,少用继承

 

以上是关于设计模式观察者模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式补充:回调模式事件监听器模式观察者模式(转)

设计模式观察者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

观察者模式

未调用 LiveData 观察者

设计模式之美(c++)-笔记-56-观察者模式

设计模式之美(c++)-笔记-56-观察者模式