Header First设计模式学习笔记——观察者模式

问题引入java

        生成一个公告板显示当时的天气情况,当天气情况发生改变的时候公告板能够实时的更新。
编程

模式定义ide

        定义对象之间的一对多的依赖,当一个对象改变状态时,它的全部依赖者都会自动收到通知并自动更新。this

认识模式spa

        该模式在生活中是很常见的。想一想生活中的各类各样的检测系统,报警系统,一旦有重要事件发生时,有关系统总能及时的收到通知,这就是观察者模式。
.net

问题解决code

        关于观察者模式,java实际上给了咱们内置的支持(能够看出该模式仍是很经常使用的吧!)可是咱们常常会本身实现。为何呢?咱们后面会给出答案。
orm

        被观察者咱们称之为主题(Subject),相应的有观察者(Observer)。
server

1、自定义实现对象

      1)  Subject,Observer咱们都定义为接口

package my.oschina.net.design.observer.owndesign;

public interface Subject {
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObserver();		
}

public interface Observer {
	void update(Subject sub);
}

    2)实现Subject和Observer接口(主题与观察者的实现)    

        a)主题实现

package my.oschina.net.design.observer.finaldesign;

import java.util.ArrayList;

public class WeatherData implements Subject{
	
	//被观测的指标数据
	private float temp;
	private float humidity;
	private float pressure;
	
	//维护一个订阅过的Observer列表
        private ArrayList<Observer> Observers;
	
	public WeatherData()
	{
		this.Observers = new ArrayList<Observer>();
	}

	@Override
	//增长Observer
	public void registerObserver(Observer o) {
		// TODO Auto-generated method stub
		Observers.add(o);		
	}

	@Override
	//移除部分Observer
	public void removeObserver(Observer o) {
		// TODO Auto-generated method stub
		int i = Observers.indexOf(o);
		if(i != -1)
			Observers.remove(Observers.indexOf(o));		
	}
	
	@Override
	//通知订阅过的Observer
	public void notifyObserver() {
		// TODO Auto-generated method stub
		for(Observer o : Observers)
		{
			o.update(this);
		}
	}
	
	public void setStatus(float temp, float humidity, float pressure)
	{
		this.temp = temp;
		this.humidity = humidity;
		this.pressure = pressure;	
		
		statusChanged();
	}
	
	public void statusChanged()
	{
		notifyObserver();
	}
	
	float getTemp()
	{
		return temp;
	}
	
	float getHumidity()
	{
		return humidity;
	}
	
	float getPressure()
	{
		return pressure;
	}	
}

          b)观察者实现

package my.oschina.net.design.observer.finaldesign;

public class CurrentConditionDisplay implements Observer,Display{
	
	//接收被观测者发过来的数据
	private float temp;
	private float humidity;
	private float pressure;
	//保存这个主题对象,可能后续有退订的需求
	private WeatherData weatherData;
	
	public CurrentConditionDisplay(WeatherData weahterdata)
	{
		this.weatherData = weahterdata;
		weatherData.registerObserver(this);
	}
	
	@Override
	public void update(Subject sub) {
		// TODO Auto-generated method stub
		
		if(sub instanceof WeatherData)
		{
			WeatherData weatherdata = (WeatherData)sub;
			this.temp = weatherdata.getTemp();
			this.humidity = weatherdata.getHumidity();
			this.pressure = weatherdata.getPressure();
		}
		
		display();
	}

	@Override
	public void display() {
		// TODO Auto-generated method stub
	System.out.println("Temp --> " + temp + "humidity --> " +humidity + "pressure -->" + pressure);
	}

}

        3)Test一下

package my.oschina.net.design.observer.finaldesign;

public class ObserverTest1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
	    WeatherData weatherdata = new WeatherData();
	    
		CurrentConditionDisplay cc = new CurrentConditionDisplay(weatherdata);
		
		weatherdata.setStatus(12, 12, 12);
		weatherdata.setStatus(13, 13, 13);
		weatherdata.setStatus(14, 14, 14);		
	}
}

        4)结果截图

2、java内置实现

        在java的java.util 包(pac1kage)中包含了最基本的Observable类(可观察,经过继承方式得到其方法和属性)Observer接口(观察),对你没有看错,我也没有写错,的确是Observable类Observer接口,他们相似与咱们上述本身定义的Subject和Observer接口,因为是java内置,有的时候使用它们的话真的是挺简单的,由于有好多的功能java自己已经为咱们写好了!

        其实这里你已经能够明白这种内置实现的弊端了,对就是由于Observable是个类!在java中只支持单继承,因此啊,这就限制了继承他的类使用的灵活性!

java内置的不一样

    a)关于主题对象

        当咱们自定义观察者的时候当须要通知观察者的时候咱们直接调用notifyO不servers()方法便可, 可是java内置的方法不是这样的,咱们须要两步走:

                1>调用setChanged()方法,标记状态已改变;

                2>调用notifyObserver()方法,完成通知的工做。

 深刻-------->setChanged()

                咱们来看看Observable内部的实现

   setChanged()
   {
       cahnged = true;
   }
  
   notifyObservers(Object arg)
   {
       if(cahnged)
       {
           for every obsrver on the list
           {
               call update(this, arg)
           }
           cahngd = false;
       }
   }
   
    notifyObservers()
    {
        notifyObservers(null)
    }

         看到这里有人可能要问了:为何要设置一个标志呢???仔细想一想,假设你是公司老总,天天要批一系列文件,好了,如今秘书送来一份文件你批了,一分钟没到,又有新的文件产生了,秘书又送了过来,而后。。。而后。。。你受得了吗?你可能会对秘书说:小李啊,这个文件你给我每50份一批给我送过来,我一并批阅!有时候咱们并不但愿被观察者有一丝的变化立刻就通知咱们,咱们能够等被观察者达到必定的程度的时候(好比说等温度上升5℃之内没必要通知系统,一旦超过5℃就通知系统!)再通知咱们,你能够想一想这样好处不少!因此当达到标准,咱们须要通知观察者的时候调用setChanged()方法还真是不错的哦!

    b)关于观察者

                update的方法略有不一样update(Observable o, Object arg),第一个参数是主题自己,第二个参数为传入notifyObserver()的数据对象,没有为空。这里就来决定是由被观察者push数据,仍是有观察者本身pull数据。

代码走起         

1)被观察者实现(注意import相应的package)

package my.oschina.net.design.observer.javautil;

import java.util.Observable;
import java.util.Observer;
/**
 * 这种方式有一个弊端就是说Observable是一个 类而不是一个接口所以它限制了这个类的使用
 * @author Eswin
 *
 */
public class WeatherData extends Observable{
	
	//被观测的指标数据
	private float temp;
	private float humidity;
	private float pressure;

	public WeatherData(){}
	
	public void setStatus(float temp, float humidity, float pressure)
	{
		this.temp = temp;
		this.humidity = humidity;
		this.pressure = pressure;	
		
		statusChanged();
	}
	
	public void statusChanged()
	{
		setChanged();
		notifyObservers();
	}
	
	public float getTemp()
	{
		return temp;
	}
	
	public float getHumidity()
	{
		return humidity;
	}
	
	public float getPressure()
	{
		return pressure;
	}

	
}

2)观察者实现

package my.oschina.net.design.observer.javautil;

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

import my.oschina.net.design.observer.owndesign.Display;

public class CurrentConditionDisplay implements Observer, Display{

	private float temp;
	private float humidity;
	private float pressure;
	
	private Observable observable;
	
	public CurrentConditionDisplay(Observable observable)
	{
		this.observable = observable;
		observable.addObserver(this);
		
	}
	
	@Override
	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub
		if(o instanceof WeatherData)
		{
			WeatherData weatherdata = (WeatherData)o;
			this.temp = weatherdata.getTemp();
			this.humidity = weatherdata.getHumidity();
			this.pressure = weatherdata.getPressure();
		}
		
		display();
		
	}

	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("Temp --> " + temp + "humidity --> " +humidity + "pressure -->" + pressure);
	}

}

3)Test一下

package my.oschina.net.design.observer.javautil;

public class ObserverTest2 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub		
	        WeatherData weatherdata = new WeatherData();
	        	    
		CurrentConditionDisplay cc = new CurrentConditionDisplay(weatherdata);
		
		weatherdata.setStatus(12, 12, 12);
		weatherdata.setStatus(13, 13, 13);
		weatherdata.setStatus(14, 14, 14);
	}
}

 4)结果截图

模式延伸

    其实咱们咱们在编程的过程当中有不少时候都运用到了观察者模式,想一想Swing,还有JavaBean,还有RMI。

模式建议

    1)要注意Observable这个类所带来的问题;

    2)有必要的话本身实现Observable也就是主题,很简单(三个方法实现就能够了)。

相关文章
相关标签/搜索