观察者模式是关于多个对象想知道一个对象中数据变化情况的一种成熟模式。观察者模式中有一个称作“主题”的对象和若干个称作“观察者”的对象,“主题”和“观察者”之间是一种一对多的依赖关系
。当“主题”的状态发生变化时,所有“观察者”都得到通知。
观察者模式的优点:
具体主题和具体关擦或者是松耦合关系,由于主题接口仅仅依赖于观察者的接口,因此具体主题只是知道它的观察者是实现观察者接口的某个实例,但不需要知道具体是哪个类。同样,忧郁观察者
仅仅依赖主题接口,因此具体观察者只是知道它依赖的主题是实现主题接口的某个类的实例,但不需要知道是具体哪个类
观察模式满足“开-闭原则”主题接口仅仅依赖于观察者的接口,这样就可以让创建具体主题的类也仅仅是依赖与观察者接口。因此如果增加新的实现观察者接口的类,不必修改创建具体主题的类
的代码。同样,创建具体观察者的类仅仅依赖与主题接口,如果增加新的实现主题接口的类,也不必修改创建具体观察者的代码
示例:
李先生希望及时知道气象站的天气预报及旅行社的每日旅行信息
李先生就是具体的一个观察者,而气象站及旅行社就成为了主题。
1、主题接口规定了具体主题需要实现的添加,删除及通知观察者更新数据的方法
package org.zhy.observer.demo02.subject;
import org.zhy.observer.demo02.observer.Observer;
/**
* 主题
* @author zhengyi
*
*/
public interface Subject {
public void addObserver(Observer o);//添加观察者
public void delObserver(Observer o);//移除观察者
public void notfilyObserver();
}
2、观察者接口规定了具体观察者用来更新数据的方法
package org.zhy.observer.demo02.observer;
import org.zhy.observer.demo02.subject.Subject;
/**
* 观察者
* @author zhengyi
*
*/
public interface Observer {
public void update(Subject subject);
}
3、具体主题-》气象站
package org.zhy.observer.demo02.subject.impl;
import java.util.ArrayList;
import org.zhy.observer.demo02.observer.Observer;
import org.zhy.observer.demo02.subject.Subject;
/**
* 具体主题
*
* @author zhengyi
*
*/
public class WeatherStation implements Subject {
String forecastTime, forecastMess;
int maxTemperature, minTemperature;
ArrayList<Observer> personList;
public WeatherStation() {
personList = new ArrayList<Observer>();
}
@Override
public void addObserver(Observer o) {
if ((o != null) && (!personList.contains(o))) {
personList.add(o);
}
}
@Override
public void delObserver(Observer o) {
if (o != null) {
personList.remove(o);
}
}
// 通知所有观察者
@Override
public void notfilyObserver() {
for (int i = 0; i < personList.size(); i++) {
Observer o = personList.get(i);
o.update(this);
}
}
/**
* 新消息
*
* @param t
* @param mess
* @param max
* @param min
*/
public void doForecast(String t, String mess, int max, int min) {
this.forecastTime = t;
this.forecastMess = mess;
this.maxTemperature = max;
this.minTemperature = min;
notfilyObserver();// 如果有新的消息则调用通知观察者函数
}
public String getForecastTime() {
return forecastTime;
}
public String getForecastMess() {
return forecastMess;
}
public int getMaxTemperature() {
return maxTemperature;
}
public int getMinTemperature() {
return minTemperature;
}
}
4、具体主题-》旅行社
package org.zhy.observer.demo02.subject;
import org.zhy.observer.demo02.observer.Observer;
/**
* 主题
* @author zhengyi
*
*/
public interface Subject {
public void addObserver(Observer o);//添加观察者
public void delObserver(Observer o);//移除观察者
public void notfilyObserver();
}
package org.zhy.observer.demo02.observer;
import org.zhy.observer.demo02.subject.Subject;
/**
* 观察者
* @author zhengyi
*
*/
public interface Observer {
public void update(Subject subject);
}
package org.zhy.observer.demo02.subject.impl;
import java.util.ArrayList;
import org.zhy.observer.demo02.observer.Observer;
import org.zhy.observer.demo02.subject.Subject;
/**
* 具体主题
*
* @author zhengyi
*
*/
public class WeatherStation implements Subject {
String forecastTime, forecastMess;
int maxTemperature, minTemperature;
ArrayList<Observer> personList;
public WeatherStation() {
personList = new ArrayList<Observer>();
}
@Override
public void addObserver(Observer o) {
if ((o != null) && (!personList.contains(o))) {
personList.add(o);
}
}
@Override
public void delObserver(Observer o) {
if (o != null) {
personList.remove(o);
}
}
// 通知所有观察者
@Override
public void notfilyObserver() {
for (int i = 0; i < personList.size(); i++) {
Observer o = personList.get(i);
o.update(this);
}
}
/**
* 新消息
*
* @param t
* @param mess
* @param max
* @param min
*/
public void doForecast(String t, String mess, int max, int min) {
this.forecastTime = t;
this.forecastMess = mess;
this.maxTemperature = max;
this.minTemperature = min;
notfilyObserver();// 如果有新的消息则调用通知观察者函数
}
public String getForecastTime() {
return forecastTime;
}
public String getForecastMess() {
return forecastMess;
}
public int getMaxTemperature() {
return maxTemperature;
}
public int getMinTemperature() {
return minTemperature;
}
}
package org.zhy.observer.demo02.subject.impl;
import java.util.ArrayList;
import org.zhy.observer.demo02.observer.Observer;
import org.zhy.observer.demo02.subject.Subject;
public class TravelAgency implements Subject {
String tourStartTime;
String tourMess;
ArrayList<Observer> personList;
public TravelAgency() {
personList = new ArrayList<Observer>();
}
@Override
public void addObserver(Observer o) {
if ((o != null) && (!personList.contains(o))) {
personList.add(o);
}
}
@Override
public void delObserver(Observer o) {
if (o != null) {
personList.remove(o);
}
}
@Override
public void notfilyObserver() {
for (int i = 0; i < personList.size(); i++) {
Observer o = personList.get(i);
o.update(this);
}
}
public void giveMess(String time, String mess) {
this.tourMess = mess;
this.tourStartTime = time;
notfilyObserver();
}
public String getTourMess() {
return tourMess;
}
public String getTourStartTime() {
return tourStartTime;
}
}
5、具体观察者-》张先生
package org.zhy.observer.demo02.observer.impl;
import org.zhy.observer.demo02.observer.Observer;
import org.zhy.observer.demo02.subject.Subject;
import org.zhy.observer.demo02.subject.impl.TravelAgency;
import org.zhy.observer.demo02.subject.impl.WeatherStation;
public class Person implements Observer {
Subject travelSubject, weatherSubject;
String forecatsTime, forecastMess;
int maxTemp, minTemp;
String tourStartTime, tourMess;
public Person(Subject travelSubject, Subject weatherSubject) {
this.travelSubject = travelSubject;
this.weatherSubject = weatherSubject;
travelSubject.addObserver(this);
weatherSubject.addObserver(this);
}
@Override
public void update(Subject subject) {
if (subject instanceof WeatherStation) {
WeatherStation we = (WeatherStation) subject;
forecastMess = we.getForecastMess();
forecatsTime = we.getForecastTime();
maxTemp = we.getMaxTemperature();
minTemp = we.getMinTemperature();
System.out.println("天气预报:" + forecatsTime + "," + ",天气状况:"
+ forecastMess + ",最高温度:" + maxTemp + ",最低温度" + minTemp);
} else if (subject instanceof TravelAgency) {
TravelAgency tr = (TravelAgency) subject;
tourMess = tr.getTourMess();
tourStartTime = tr.getTourStartTime();
System.out.println("旅游开始日期:" + tourStartTime + ",旅游信息:" + tourMess);
}
}
}
6、程序调用
package org.zhy.observer.demo02;
import org.zhy.observer.demo02.observer.impl.Person;
import org.zhy.observer.demo02.subject.impl.TravelAgency;
import org.zhy.observer.demo02.subject.impl.WeatherStation;
public class Appliction {
public static void main(String[] args) {
WeatherStation we=new WeatherStation();
TravelAgency ta=new TravelAgency();
Person mrLi=new Person(ta, we);
we.doForecast("10号", "阴有小雨", 28, 20);
ta.giveMess("10日", "黄山两日游");
we.doForecast("11号", "晴", 30, 15);
ta.giveMess("11日", "华山一日游");
}
}
运行结果:
适合观察者模式的情景
1、当一个对象的数据更新时需要通知其他对象,但这个对象又不希望被通知的对象形成紧耦合
2、当一个对象的数据更新时,这个对象需要让其他对象也鸽子更新自己的数据,但这个对象不知道具体有多少对象需要更新数据