博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Header First设计模式学习笔记——观察者模式
阅读量:6901 次
发布时间:2019-06-27

本文共 6569 字,大约阅读时间需要 21 分钟。

hot3.png

问题引入

        生成一个公告板显示当时的天气状况,当天气状况发生改变的时候公告板可以实时的更新。

模式定义

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

认识模式

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

问题解决

        关于观察者模式,java实际上给了我们内置的支持(可以看出该模式还是很常用的吧!)但是我们经常会自己实现。为什么呢?我们后面会给出答案。

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

一、自定义实现

      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
 Observers; public WeatherData() { this.Observers = new ArrayList
(); } @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)结果截图

134737_UqSk_1446623.jpg

二、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)结果截图

134737_UqSk_1446623.jpg

模式延伸

    其实我们我们在编程的过程中有很多时候都运用到了观察者模式,想想Swing,还有JavaBean,还有RMI。

模式建议

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

    2)有必要的话自己实现Observable也就是主题,很简单(三个方法实现就可以了)。

转载于:https://my.oschina.net/v5871314/blog/222195

你可能感兴趣的文章
如何用oracle从身份证信息中提取出生日期?
查看>>
Keil C编译器的变量存储分配
查看>>
非常不错的js 屏蔽类加验证类
查看>>
Innodb间隙锁,细节讲解(转)
查看>>
Apache安装
查看>>
C语言练习题库----数组
查看>>
算法的时间复杂度详解
查看>>
制作3D旋转视频展示区
查看>>
Spring.Net初认识——竹子整理
查看>>
win7 下 vmware 虚拟机开后 w字母键失效不能用 解决方案:
查看>>
[网络流24题-8]汽车加油行驶问题
查看>>
Vim使用技巧(2) -- 插入模式技巧 【持续更新】
查看>>
Spring MVC+Fastjson之时间类型序列化
查看>>
【ospf-路由过滤】
查看>>
进阶: 案例八: Drag and Drop(动态)
查看>>
Remove Duplicates from Sorted List II
查看>>
Python中else的用法
查看>>
蓝桥杯 迷宫
查看>>
多行截断
查看>>
完成个人中心 导航标签
查看>>