设计模式(二)—— 观察者模式

 

由于之前看的容易忘记,因此特记录下来,以便学习总结与更好理解,该系列博文也是第一次记录,所有有好多不完善之处请见谅与留言指出,如果有幸大家看到该博文,希望报以参考目的看浏览,如有错误之处,谢谢大家指出与留言。

一、观察者模式原理

1、Internet气象站项目,普通OO设计方案,有些问题(扩展不是很好)

案例:

    1.1、Internet气象站项目:

         设计:    提供温度、气压和湿度的接口 

                        测量数据更新时需时时通知给第三方

                        需要设计开放型API,便于其他第三方公司也能接入气象站获取数据

   1.2、WeatherData类

         1.1.1、一个通常的设计方案

设计一个公告板类 (后面优化成接口  放入WeatherData类中)

普通OO设计方案代码如下:

公告板类:

package com.java.hexter.internetweather;

public class CurrentConditions {
	
	private float mTemperature;
	private float mPressure;
	private float mHumidity;
	
	public void update(float mTemperature,float mPressure,float mHumidity)
	{
		this.mTemperature=mTemperature;
		this.mPressure=mPressure;
		this.mHumidity=mHumidity;
		display();
	}
	
	public void display()
	{
		System.out.println("***Today mTemperature: "+mTemperature+"***");
		System.out.println("***Today mPressure: "+mPressure+"***");
		System.out.println("***Today mHumidity: "+mHumidity+"***");
	}
}

气象站类:

package com.java.hexter.internetweather;

public class WeatherData {
	
	private float mTemperatrue;
	private float mPressure;
	private float mHumidity;
	private CurrentConditions mCurrentConditions;
	public WeatherData(CurrentConditions mCurrentConditions)
	{
	this. mCurrentConditions= mCurrentConditions;
	}
	
	public float getTemperature()
	{
		return mTemperatrue;
		
	}
	
	public float getPressure()
	{
		return mPressure;
		
	}
	
	public float getHumidity()
	{
		return mHumidity;
		
	}
	public void dataChange()
	{
		mCurrentConditions.update(getTemperature(), getPressure(), getHumidity());
		}
	
	public void setData(float mTemperature,float mPressure,float mHumidity)
	{
		this.mTemperatrue=mTemperature;
		this.mPressure=mPressure;
		this.mHumidity=mHumidity;
		dataChange();
	}
	
}

测试类:

package com.java.hexter.internetweather;

public class InternetWeather {

	public static void main(String[] args) {
		CurrentConditions mCurrentConditions;
		WeatherData mWeatherData;
		
		mCurrentConditions=new CurrentConditions();
		mWeatherData=new 		WeatherData(mCurrentConditions);
		
		mWeatherData.setData(30, 150, 40);
	}

}

     1.1.2、有些问题

          1)其他第三方公司接入气象站获取数据的问题

           2)无法在运行时动态的添加第三方   扩展性很差

2、引入观察者模式概念   (通过方法论思考:通过变化的和不变化的部分,把变化的抽离出来)

     2.1、观察者模式就像定牛奶业务(其实就是用户在奶站那里订阅牛奶,首先需要先登记在奶站,然后用户就可以通过电话等方式告诉奶站订阅不同牛奶,或者告诉奶站不再订阅。当然奶站有新品种也会通知用户,这就是上面的公告板。)举例如下:

          1)奶站,Subject

           2)用户,Observer

    2.2、Subject:登记注册、移除和通知

    2.3、Observer:接收输入

注意:就是通知时候有两种方式:直接通知给Observer和观察者Observer自己去拉数据;细节使用根据参数大小等等业务问题来取用。

    2.4、观察者模式: 对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对 象为Observer,Subject通知Observer变化

3、新的设计方案

    3.1、用观察者模式设计重新设计的方案

被依赖的对象为Subject,依赖的对 象为Observer,Subject通知Observer变化

这里的Subject相当于之前的WeatherData(气象站)这里定义WeatherDataSt作为区别

这个WeatherDataSt原来的而功能不变,在此基础添加了注册Observer和溢出Observer等功能。

这个Subject接口其实就是用于第三方公司等的一些用户注册,移除,通知等操作。Observer设计成一个观察者接口,这个接口实例化后,其实是一些,公告板,要接入的一些第三方公司等等,就是外面要接入,要实现这个接口。然后观察者通过气象站需要数据时,可以注册,移除等等只要实现update就行。当气象站有数据时,改变数据时候,就会调用通过dataChange()方法,然通过调用通知方法,去通知注册的用户,直接通知数据或者用户去取数据。下面这个案例是采用气象站有数据变化时,去通知观察者模式。

其中WeatherDataSt实现Subject接口,公告板CurrentConditions实现Observer接口,所以各种公告板相当于观察者Observer,以此类推。

代码如下:

Subject:

package com.java.hexter.internetweather.observer;

public interface Subject {
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObservers();
}
package com.java.hexter.internetweather.mode;

import java.util.ArrayList;

import com.java.hexter.internetweather.observer.Observer;
import com.java.hexter.internetweather.observer.Subject;

public class WeatherDataSt implements Subject{
	
	private float mTemperatrue;
	private float mPressure;
	private float mHumidity;
	private ArrayList<Observer> mObservers;
	public WeatherDataSt()
	{
		mObservers=new ArrayList<Observer>();
	}
	
	public float getTemperature()
	{
		return mTemperatrue;
		
	}
	
	public float getPressure()
	{
		return mPressure;
		
	}
	
	public float getHumidity()
	{
		return mHumidity;
		
	}
	public void dataChange()
	{
		notifyObservers();
	}

	

	
	
	
	public void setData(float mTemperatrue,float mPressure,float mHumidity)
	{
		this.mTemperatrue=mTemperatrue;
		this.mPressure=mPressure;
		this.mHumidity=mHumidity;
		dataChange();
	}

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

	@Override
	public void removeObserver(Observer o) {
		// TODO Auto-generated method stub
		if(mObservers.contains(o))
		{mObservers.remove(o);}
	}

	@Override
	public void notifyObservers() {
		// TODO Auto-generated method stub
		for(int i=0,len=mObservers.size();i<len;i++)
		{
			mObservers.get(i).update(getTemperature(), getPressure(), getHumidity());
		}
	}

}

Observer:

package com.java.hexter.internetweather.observer;

public interface Observer {
	public void update(float mTemperatrue,float mPressure,float mHumidity);
}

各种公告板实现:

ForcastConditions公告板

package com.java.hexter.internetweather.mode;

import com.java.hexter.internetweather.observer.Observer;


public class ForcastConditions implements Observer{
	private float mTemperatrue;
	private float mPressure;
	private float mHumidity;
	@Override
	public void update(float mTemperatrue, float mPressure, float mHumidity) {
		// TODO Auto-generated method stub
		this.mTemperatrue=mTemperatrue;
		this.mPressure=mPressure;
		this.mHumidity=mHumidity;
		
		display();
	}
	public void display()
	{
		System.out.println("**鏄庡ぉ娓╁害:"+(mTemperatrue+Math.random())+"**");
		System.out.println("**鏄庡ぉ姘斿帇:"+(mPressure+10*Math.random())+"**");
		System.out.println("**鏄庡ぉ婀垮害:"+(mHumidity+Math.random())+"**");
	}
}

CurrentConditions公告板

package com.java.hexter.internetweather.mode;

import com.java.hexter.internetweather.observer.Observer;

public class CurrentConditions implements Observer {

	private float mTemperatrue;
	private float mPressure;
	private float mHumidity;

	@Override
	public void update(float mTemperatrue, float mPressure, float mHumidity) {
		// TODO Auto-generated method stub
		this.mHumidity = mHumidity;
		this.mPressure = mPressure;
		this.mTemperatrue = mTemperatrue;
		display();
	}

	public void display() {
		System.out.println("***Today mTemperatrue:" + mTemperatrue + "***");
		System.out.println("***Today mPressure:" + mPressure + "***");
		System.out.println("***Today mHumidity:" + mHumidity + "***");

	}

}

测试代码:

package com.java.hexter.internetweather.mode;



public class InternetWeather {

	public static void main(String[] args) {
		
		CurrentConditions mCurrentConditions;
		ForcastConditions mForcastConditions;
		WeatherDataSt mWeatherDataSt;
		
		mWeatherDataSt=new WeatherDataSt();
		mCurrentConditions=new CurrentConditions();
		mForcastConditions=new ForcastConditions();
		
		mWeatherDataSt.registerObserver(mCurrentConditions);
		mWeatherDataSt.registerObserver(mForcastConditions);
		
		mWeatherDataSt.setData(30, 150, 40);
		mWeatherDataSt.removeObserver(mCurrentConditions);
		mWeatherDataSt.setData(40, 250, 50);
	}

}

二、Java内置观察者(原理就是观察者原理,注意是:Observer是个类,注册等方法已经实现了,有好处也有不好的地方)

1、Java内置的观察者

    Observable 是个类 注册等方法已经实现比较方便, 但是不能做到多重继承,同时通知时一定要先执行setChange().不执行,通知是不起作用的。

     Observer   上面是个接口

2、用Java内置观察者重新设计该项目

3、内置观察者的注意点 Observable是类而不是接口

注意点:(1)、Java内置的观察者实现了拉和推数据。(2)、在通知前一定要setChange,提高了灵活性。(3)、Observer设置成类的好处不用在去实现,但没法定制化,和主动实现注册等功能比较麻烦,Observer等类不能实现多种继承等等。

三、观察者模式关键点

1、示例项目中问题分析

2、观察者模式的意义

3、松耦合、高内聚、隔离影响的意义

4、使用Java内置观察者的注意点

详细学习代码案例包块 内置观察者模式代码:https://download.csdn.net/download/gududedabai/10620878

想要完整代码可以留下邮箱,我会及时发送。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
观察者模式是一种常见的设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。在这个模式中,被观察者对象通常称为主题(Subject),而观察者对象通常称为观察者(Observer)。 下面我们就以一个简单的天气预报系统为例来介绍观察者模式的使用。 首先,我们需要定义一个主题接口(Subject),它包含了添加、删除和通知观察者的方法: ```java public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); } ``` 然后,我们需要定义一个观察者接口(Observer),它包含了更新数据的方法: ```java public interface Observer { public void update(float temp, float humidity, float pressure); } ``` 接下来,我们需要定义一个具体的主题类(WeatherData),它实现了主题接口,并包含了一个列表来存储观察者对象,以及当前的温度、湿度和气压等数据: ```java import java.util.ArrayList; 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 (int i = 0; i < observers.size(); i++) { Observer observer = (Observer)observers.get(i); 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(); } // other WeatherData methods here } ``` 最后,我们需要定义一个具体的观察者类(CurrentConditionsDisplay),它实现了观察者接口,并在更新数据时打印出当前的温度、湿度和气压等信息: ```java 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"); } } ``` 现在,我们可以创建一个天气预报系统,它包含了一个主题对象和一个观察者对象,并通过调用主题对象的方法来更新数据和通知观察者: ```java public class WeatherStation { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); weatherData.setMeasurements(80, 65, 30.4f); weatherData.setMeasurements(82, 70, 29.2f); weatherData.setMeasurements(78, 90, 29.2f); } } ``` 以上就是一个简单的观察者模式的例子,它可以让我们更好地理解和应用这个常见的设计模式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平凡之路无尽路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值