`
schy_hqh
  • 浏览: 546426 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

HeadFirst(二)Observer 观察者模式

 
阅读更多

出版者+订阅者=观察者模式

出版者:主题 Subject

订阅者:观察者 Observer

 

观察者模式

在对象之间定义一对多的依赖关系,当一个对象(主题)改变状态时,它的所有依赖者(观察者)都将收到通知,并自动更新。

 

主题与观察者之间通过组合关系完成相互的调用:

所有观察者Observer持有相同的一个主题Subject,观察者通过该接口向主题进行注册;

主题Subject持有观察者的一个集合List<Observer>,主题遍历集合向每个观察者发送通知

 

设计原则

为了交互对象之间的松耦合设计而努力;

找出程序中会变化的方面,然后将其和固定不变的方面相分离。(观察者的类型和个数是变化的);

针对接口编程,不针对实现编程。(主题与观察者都是接口,主题也可以有多个实现);

多用组合,少用继承。(通过依赖完成关系的建立);

 

 

================================================================================

 
 

实例

 

主题接口

package Subject;

import Observer.Observer;

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

具体的主题

package Subject;

import java.util.ArrayList;
import java.util.List;

import Observer.Observer;

public class WeatherData implements Subject {
	private float temperature;
	private float humidity;
	private float pressure;
	
	//一对多关系
	//观察者的集合 
	private List<Observer> observers;
	
	public WeatherData() {
		this.observers = new ArrayList<Observer>();
	}
	
	/**
	 * 注册到主题中
	 */
	@Override
	public void registerObserver(Observer o) {
		this.observers.add(o);
	}
	/**
	 * 取消订阅
	 */
	@Override
	public void removeObserver(Observer o) {
		int index = this.observers.indexOf(o);
		if(index!=-1)
			this.observers.remove(o);
	}
	
	/**
	 * 一旦状态发生变化,通知所有的观察者
	 */
	@Override
	public void notifyObservers() {
		for(Observer o : observers)
			o.update(temperature, humidity, pressure);
	}
	
	
	public void measurementChanged() {
		notifyObservers();
	}
	
	public void setMessurements(float temprature, float humidity, float pressure) {
		this.temperature = temprature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementChanged();
	}

}

 

观察者的接口

package Observer;

public interface Observer {
	/**
	 * 观察者提供给主题使用的接口
	 */
	public  void update(float temp, float humidity, float pressure);
}

 

观察者需要实现的另一个接口-布告栏接口

package display;

public interface DisplayElement {
	public void display();
}

 

具体的观察者

package Observer;

import Subject.Subject;
import display.DisplayElement;

public class CurrentConditionDisplay implements Observer, DisplayElement {
	
	private float temperature;
	private float humidity;
	
	//持有主题的引用,完成对主题的注册与取消订阅
	private Subject weatherData;
	
	
	public CurrentConditionDisplay(Subject weatherData) {
		this.weatherData = weatherData;
		//注册
		this.weatherData.registerObserver(this);
	}

	@Override
	public void update(float temp, float humidity, float pressure) {
		this.temperature = temp;
		this.humidity = humidity;
		display();
	}

	@Override
	public void display() {
		System.out.println("Current Condition: tempratute="+temperature+", humidity="+humidity);
	}
}

 

package Observer;

import Subject.Subject;
import display.DisplayElement;

public class StatisticsDisplay implements Observer, DisplayElement {
	
	private float temperature;
	private float humidity;
	
	//持有主题的引用,完成对主题的注册与取消订阅
	private Subject weatherData;
	
	
	public StatisticsDisplay(Subject weatherData) {
		this.weatherData = weatherData;
		//注册
		this.weatherData.registerObserver(this);
	}

	@Override
	public void update(float temp, float humidity, float pressure) {
		this.temperature = temp;
		this.humidity = humidity;
		display();
	}

	@Override
	public void display() {
		System.out.println("StatisticsDisplay: tempratute="+temperature+", humidity="+humidity);
	}
}

 

package Observer;

import Subject.Subject;
import display.DisplayElement;

public class ForeastDisplay implements Observer, DisplayElement {
	
	private float temperature;
	private float humidity;
	
	//持有主题的引用,完成对主题的注册与取消订阅
	private Subject weatherData;
	
	
	public ForeastDisplay(Subject weatherData) {
		this.weatherData = weatherData;
		//注册
		this.weatherData.registerObserver(this);
	}

	@Override
	public void update(float temp, float humidity, float pressure) {
		this.temperature = temp;
		this.humidity = humidity;
		display();
	}

	@Override
	public void display() {
		System.out.println("ForeastDisplay: tempratute="+temperature+", humidity="+humidity);
	}
}

 

测试

package test;
import Observer.CurrentConditionDisplay;
import Observer.ForeastDisplay;
import Observer.StatisticsDisplay;
import Subject.WeatherData;


public class WeatherDataTest {
	public static void main(String[] args) {
		WeatherData weatherData = new WeatherData();
		
		CurrentConditionDisplay currentDisplay =  new CurrentConditionDisplay(weatherData);
		StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
		ForeastDisplay foreastDisplay = new ForeastDisplay(weatherData);
		
		weatherData.setMessurements(31.03f, 29.33f, 100.21f);
		
		//取消订阅的职责是否应该放到观察者中进行更合适?
		weatherData.removeObserver(foreastDisplay);
		System.out.println("remove foreastDisplay...");
		weatherData.setMessurements(22.03f, 33.33f, 44.21f);
	}
}

 

 

================================================================================

 

使用JAVA内置的观察者模式

Observable的黑暗面---Observable是一个类而不是一个接口,它甚至没有实现一个接口。

如果要使用JAVA提供的这个Observable的行为,只能通过继承才能得到,这样便让子类非常的为难,最终限制了Observable的复用潜力。

setChanged()在Observable类中被保护起来了,除非继承Observable,否则无法创建Observable实例并组合到自己的对象中。

在子类中,通过Observable类中protected权限的setChanged()方法,去改变Observable类中的私有属性boolean changed = true,完成状态的切换!!!

 

主题

package Subject;

import java.util.Observable;

/**
 * 主题
 * 主题继承JAVA提供的内置主题
 * 由于JAVA提供的Observable是一个类,要想使用JAVA内置的这个功能,只能采用继承
 * 
 */
public class WeatherData2 extends Observable {
	
	private float temperature;
	private float humidity;
	private float pressure;
	
	
	public void measurementChanged() {
		//指示状态已发生变化,可以通知观察者了。扩展点:这里可以设置条件,当条件满足时才发出通知,而不是每次变化都通知!
		setChanged();
		//通知所有的观察者
		notifyObservers();
	}
	
	public void setMessurements(float temprature, float humidity, float pressure) {
		this.temperature = temprature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementChanged();
	}

	public float getTemperature() {
		return temperature;
	}

	public float getHumidity() {
		return humidity;
	}

	public float getPressure() {
		return pressure;
	}

}

 

观察者需要实现的布告栏接口

package display;

public interface DisplayElement {
	public void display();
}

 

 

观察者

package Observer;

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

import Subject.WeatherData2;
import display.DisplayElement;

/**
 * 观察者
 * 使用JAVA提供的内置观察者接口
 *
 */
public class CurrentConditionDisplay2 implements Observer, DisplayElement {
	//主题接口
	Observable observable;
	
	private float temperature;
	private float humidity;
	
	public CurrentConditionDisplay2(Observable observable){
		//为主题接口指定具体实现类
		this.observable = observable;
		//将观察者注册到主题中
		this.observable.addObserver(this);
	}
	
	/**
	 * 采用拉的方式,由观察者自己到主题中获取需要的数据
	 * @param o	主题
	 * @param arg 主题“推送”的数据,如果不为空,则表示由主题负责“推送”数据
	 */
	@Override
	public void update(Observable o, Object arg) {
		if(o instanceof WeatherData2) {
			WeatherData2 wd = (WeatherData2)o;
			this.temperature = wd.getTemperature();
			this.humidity = wd.getHumidity();
			display();
		}
	}
	
	@Override
	public void display() {
		System.out.println("Current Condition: tempratute="+temperature+", humidity="+humidity);
	}
}

 

 

测试

package test;
import Observer.CurrentConditionDisplay2;
import Subject.WeatherData2;


public class WeatherData2Test {
	public static void main(String[] args) {
		WeatherData2 weatherData = new WeatherData2();
		
		CurrentConditionDisplay2 currentDisplay =  new CurrentConditionDisplay2(weatherData);
		
		weatherData.setMessurements(31.03f, 29.33f, 100.21f);
		
		//取消订阅的职责是否应该放到观察者中进行更合适?
		weatherData.deleteObserver(currentDisplay);
		System.out.println("remove foreastDisplay...");
		weatherData.setMessurements(22.03f, 33.33f, 44.21f);
	}
}

 

 

 

 

  • 大小: 81.6 KB
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    [行为模式]head first 设计模式之观察者模式(observer)

    NULL 博文链接:https://jacky-dai.iteye.com/blog/1132063

    《HeadFirst设计模式》观察者模式c++实现代码

    观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 Observer Pattern defines a one-to-many dependency between objects so that when one object ...

    OBserver模式设计实现

    Head First模式设计用的是Java,实现观察者模式使用C++

    Head.First设计模式_PDF.part1

    使用Java内建的观察者模式 java.util.Observable的黑暗面 设计箱内的工具 习题解答 …… 3 装饰者模式:装饰对象 4 工厂模式:烘烤OO的精华 5 单件模式:独一无二的对象 6 命令模式:封装调用 7 ...

    headfirst_observer_subject.zip_单片机开发_Java_

    设计模式观察者模式

    OOPractice:《HeadFirst 设计模式》中主要模式的具体实现

    第二章 观察者模式 observer 第三章 装饰着模式 decorater 第四章 工厂模式 factory 第五章 封装调用 methodinvocation 第六章 适配器 adapter 第七章 模板方法 template 第八章 迭代器与组合模式 iterator 第九章 ...

    02-observer-pattern

    head-first-design-pattern—02-observer-pattern(观察者模式),融入了个人的见解,里面包含错误的实现和正确的标准实现,你可以对比学习,加深对模式的理解

    DesignPattern

    观察者模式:定义了对象之间的一对多依赖(在主题类中,注册观察者类),这样一来,当一个对象(Subject主题)改变状态时,它的多有依赖者(Observer观察者)都会收到通知并自动更新。 Java提供了观察者模式的实现,...

    P2P-chat:此 P2P 聊天已实现为群聊。 单例模式、观察者模式和 MVC 模式

    #P2P 聊天 此 P2P 聊天已实现为群聊。 聊天是这样实现的: 您必须首先在同一本地服务器中使用聊天。 适应更广泛的方法并不难。 尽管如此,由于测试问题,我... ##Bibliography Head First 设计模式 - O'Reilly Media

    ObserverDemo

    用C++写的一个观察者模式的小Demo,思想来源于Head First

    java实验:设计模式2.doc

    java实验: 设计模式(单子、工厂、策略、组合、观察者模式)练习 在上次作业基础上,设计一个贩卖各类书籍的电子商务网站的购物车系统。该系统包括 的模块有: 模块1:图书目录的添加模块,实现对书本信息的增加。 ...

    java餐饮管理系统源码6-design-patterns:设计模式

    观察者模式定义了对象之间一对多的依赖, 这样一来, 当一个对象改变状态 所有依赖都会收到通知, 自动更新 :beer_mug:设计原则1: 为了交互对象之间的松耦合设计而努力 :star:实现细节 自己设计的Observer/Subject: 见 ...

    asp.net知识库

    动态控制Page页的Head信息 SubmitOncePage:解决刷新页面造成的数据重复提交问题 SharpRewriter:javascript + xml技术利用#实现url重定向 采用XHTML和CSS设计可重用可换肤的WEB站点 asp.net的网址重定向方法的比较...

    design_patterns

    design_patterns/strategy.py示例:examples/strategy_example.pyObserver Pattern(观察者模式)实现:design_patterns/observer.py示例:examples/observer_example.pyDecorator Pattern(装饰者模式)实现:...

Global site tag (gtag.js) - Google Analytics