zoukankan      html  css  js  c++  java
  • JAVA设计模式之观察者模式

    有趣的事情发生时,可千万别错过了!有一个模式可以帮你的对象知悉现况,不会错过该对象感兴趣的事。对象甚至在运行时可决定是否要继续被通知。有了观察者,你将会消息灵通。

    介绍

    观察者模式的定义:

    在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。
    

    简单理解

    为了方便理解观察者模式,我们以报社为例:

    1. 报社的业务是出版报纸;
    2. 向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会一直收到新报纸。
    3. 当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来。
    4. 只要报社还在运营,就会一直有人(或单位)

    如果你了解报社的订阅是怎么回事,其实就知道观察者是怎么回事了,只是名称不太一样:
    出版者改称为“主题”(Subject)或“被观察者”(Observable),订阅者改称为“观察者”(Observer).
    主题 + 观察者 = 观察者模式
    主题就是定义中的“一”,观察者为定义中的“多”,当主题有变化时,便会通知它的”订阅者“也就是”观察者“

    使用场景

    • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
    • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
    • 一个对象必须通知其他对象,而并不知道这些对象是谁。
    • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

    举例:有一个微信公众号服务,不定时发布一些消息,关注公众号就可以收到推送消息,取消关注就收不到推送消息。

    优缺点

    优点

    1. 观察者和被观察者是抽象松耦合的;
    2. 建立一套触发机制。

    缺点

    1. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间;
    2. 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

    注意事项

    1. JAVA 中已经有了对观察者模式的支持类;
    2. 避免循环引用;
    3. 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

    实现

    类图

    实现步骤

    创建抽象主题 - Subject

    public interface Subject {
    
    	//观察者订阅服务
    	public void registerObserver(Observer o);
    
    	//观察者取消订阅服务
    	public void removeObserver(Observer o);
    
    	//主题改变时,会被调用,通知所有观察者
    	public void notifyObservers();
    	
    }
    

    创建抽象观察者 - Observer

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

    创建具体主题

    public class WeatherData implements Subject {
    	private ArrayList<Observer> observers;
    	private float temperature;
    	private float humidity;
    	private float pressure;
    	
    	public WeatherData() {
    		observers = new ArrayList<Observer>();
    	}
    	
    	public void registerObserver(Observer o) {
    		observers.add(o);
    	}
    	
    	public void removeObserver(Observer o) {
    		int i = observers.indexOf(o);
    		if (i >= 0) {
    			observers.remove(i);
    		}
    	}
    	
    	public void notifyObservers() {
    		for (Observer observer : observers) {
    			observer.update(temperature, humidity, pressure);
    		}
    	}
    	
    	public void measurementsChanged() {
    		notifyObservers();
    	}
    	
    	public void setMeasurements(float temperature, float humidity, float pressure) {
    		this.temperature = temperature;
    		this.humidity = humidity;
    		this.pressure = pressure;
    		measurementsChanged();
    	}
    
    //	public float getTemperature() {
    //		return temperature;
    //	}
    //	
    //	public float getHumidity() {
    //		return humidity;
    //	}
    //	
    //	public float getPressure() {
    //		return pressure;
    //	}
    
    }
    

    创建一个具体观察者

    public class CurrentConditionsDisplay implements Observer {
    	private float temperature;
    	private float humidity;
    	private Subject weatherData;
    	
    	public CurrentConditionsDisplay(Subject weatherData) {
    		this.weatherData = weatherData;
    		//订阅
    		weatherData.registerObserver(this);
    	}
    	
    	public void update(float temperature, float humidity, float pressure) {
    		this.temperature = temperature;
    		this.humidity = humidity;
    		display();
    	}
    	
    	public void display() {
    		System.out.println("Current conditions: " + temperature 
    			+ "F degrees and " + humidity + "% humidity");
    	}
    }
    

    测试

    public class WeatherStation {
    
    	public static void main(String[] args) {
    
    		//创建主题
    		WeatherData weatherData = new WeatherData();
    
    		//创建观察者并订阅
    		CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
    //		StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
    //		ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
    
    		//通知观察者
    		weatherData.setMeasurements(80, 65, 30.4f);
    //		weatherData.setMeasurements(82, 70, 29.2f);
    //		weatherData.setMeasurements(78, 90, 29.2f);
    	}
    }
    

    结语

    设计模式源于生活

  • 相关阅读:
    Apache2.4.x与Apache2.2.x的一些区别
    ubuntu下的apache的虚拟主机的配置
    mysql的事物
    javascript的预编译和执行顺序
    ubuntu下的词典的安装
    ubuntu下的apache+php+mysql的安装
    mysql的架构
    session
    cookie
    JavaScript实例-----反选
  • 原文地址:https://www.cnblogs.com/J-Simon/p/10926728.html
Copyright © 2011-2022 走看看