观察者模式
观察者模式: JDK使用最多的模式之一
为了方便理解,举个例子
1.报社的业务就是出版报纸
2.订阅报纸,只要哦出版新报纸,就会给你送来
取消订阅,就不会送了
3.只要报社正常运行,就会有人订阅或者退订
在观察者模式中,报社改为 "主题(Subject)",订阅者改为"观察者(Observer)"
主题对象管理某些数据
观察者注册主题,主题数据改变时能收到更新
普通对象增加订阅,就会成为观察者对象
观察者取消订阅就会,就不会再收到更新的数据,成为普通对象
观察者模式:
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会收到通知并自动更新
观察者提供了一种对象设计,让主题和观察者之间松耦合
因为,关于观察者的一切,主题只知道观察者继承了某个接口和自己建立关系,
但是主题并不知道观察者是谁
任意时候我们都可以增减观察者.因为主题唯一依赖的东西是一个实现Observer接口的对象列表
假如出现新的观察者类,我们不需要修改主题的代码,
假如有个新的具体类需要当观察者,不需要为了兼容他而更改主题代码
主题只需发送通知给所有实现了观察者接口的对象
改变主题/观察者任意一方,并不会影响另外一方,只要他们之间的接口被遵守,就可以自由的改变他们
设计原则:
为了交互对象之间的松耦合设计而努力
松耦合的设计之所以能让我们的OO系统如此富有弹性,应对变化,是因为对象之间的依赖关系降到最低
注:OO 面向对象 Object Oriented
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservsers();//主题改变即调用
}
public interface Observer {
void update (Long temp, Long humidity,Long pressure);
}
public interface DisplayElement {
public void display();//布告板显示调次方法
} /**
* 数据站
* @author Dougest
* 2017年5月26日 上午9:03:26
*
*/
public class WeatherData implements Subject{
private ArrayList observers;
private Long temp;
private Long humidity;
private Long pressure;
public WeatherData() {
observers = new ArrayList();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if(i >= 0) observers.remove(i);
else throw new RuntimeException("取消订阅失败");
}
public void notifyObservers() {
for(int i = 0; i< observers.size(); i++) {
Observer o = (Observer) observers.get(i);
o.update(temp, humidity, pressure);
}
}
public void setChange(Long temp, Long humidity,Long pressure){
this.humidity = humidity;
this.temp = temp;
this.pressure = pressure;
notifyObservers();
}
/**
* 布告板
* @author Dougest
* 2017年5月23日
*/ //实现次接口可以在weather获取改变//所有布告板都实现接口
public class CurrentConditionsDisplay implements Observer,DisplayElement{
private Long temperature;
private Long humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("temperature: "+temperature+" humidity: "+humidity);
}
@Override
public void update(Long temperature, Long humidity, Long pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
@Test
public void test1() {
WeatherData w = new WeatherData();
CurrentConditionsDisplay c = new CurrentConditionsDisplay(w);
HeatIndexDisplay h = new HeatIndexDisplay(w);
w.setmeasurements(1l, 1l, 1l);
w.setmeasurements(2l, 2l, 2l);
w.setmeasurements(3l, 3l, 3l);
temperature: 1 humidity: 1
p1 t1
temperature: 2 humidity: 2
p2 t2
temperature: 3 humidity: 3
p3 t3
/***********************使用java内置的观察者模式************************/
java.util.Observble中notifyObserver()方法导致观察者是无序的,他不是一个接口,而是一个类,没有接口,无法建立自己的实现
但是Java是单继承,如果使用它就无法继承其他超类,
而且.serChanges()方法被保护起来了,被protected修饰
冲突了我们前面的设计原则 "多用组合,少用继承"
/***********************要点************************/
1.观察者模式定义了对象之间一对多的的关系
2.主题(可观察者)用一个共同的接口来更新观察者
3.观察者和被观察者之间使用松耦合(loosecoupling)的方式结合,可观察者不知道主题的细节,只知道观察者实现了主题的接口
4.使用次模式,你可以被主题推"推(push)"或"拉(pull)"数据(然而,推的方式被认为更加正确)
5.有多个观察者时,不可以依赖特定的通知次序
6.java有多种观察者模式的实现,包括通用的java.util.Observable
7.注意java.util.Observable带来的一些问题
8.如果有必要的话,可以实现自己的观察者模式
9.Swing大量使用观察者模式,虚度GUI框架也是如此
10.此模式也被用在很多地方,如javaBean,RMI
设计原则:
找出程序中会变化的部分,然后将其和固定不变的方面分离