定义
观察者模式定义了对象之间的一对多依赖, 当一个对象改变状态时, 它的所有依赖者都会收到通知并自动更新
**
设计原则
- 为交互对象之间的松耦合设计而努力
案例
背景: 一个气象观测站, 由weatherObject追踪天气, 温度, 气压, 有三种布告板分别显示目前的状况, 并希望布告板可以增加
建立Subject接口, 负责Observer的注册,移除以及通知
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObserver(String newTemp);
}
WeatherData实现Subject接口, 持有List
public class WeatherData implements Subject {
private List<Observer> observerList;
private String temperature;
public WeatherData() {
observerList = new ArrayList<Observer>();
}
public void change(String newTemp) {
System.out.println("气候改变了!");
notifyObserver(newTemp);
}
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int i = observerList.indexOf(observer);
if (i > 0) {
observerList.remove(i);
}
}
@Override
public void notifyObserver(String newTemp) {
for (Observer observer : observerList) {
observer.update(newTemp);
}
}
}
Observer接口有更新方法
public interface Observer {
void update(String newTemp);
}
布告板实现Observer接口, 实现更新方法, 更新自己的变量
并持有weather对象, 在构造方法中将自身注册到Subject的List
public class OneDisplay implements Observer, Display {
private String temp;
private Subject weather;
public OneDisplay(Subject weather) {
this.weather = weather;
weather.registerObserver(this);
}
@Override
public void display() {
System.out.println("这里是一号公告板, 目前的温度是: " + this.temp);
}
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
@Override
public void update(String newTemp) {
this.temp = newTemp;
}
}
测试:
@Test
public void testObserver() {
WeatherData weatherData = new WeatherData();
OneDisplay oneDisplay = new OneDisplay(weatherData);
TwoDisplay twoDisplay = new TwoDisplay(weatherData);
weatherData.change("888");
oneDisplay.display();
twoDisplay.display();
weatherData.change("999");
oneDisplay.display();
twoDisplay.display();
}
结果:
气候改变了!
这里是一号公告板, 目前的温度是: 888
这里是二号公告板, 目前的温度是: 888
气候改变了!
这里是一号公告板, 目前的温度是: 999
这里是二号公告板, 目前的温度是: 999
这样做的好处:
1.Subject与Observer完全松耦合, Observer可以自由增加, 将自身注册到Subject中即可
2.面对接口编程
3.当Subject发生变化时, 通知所有的Observer, 所有的Observer会执行update
联系以上, 即容易理解概念
java内置的观察者模式
被观察者继承Observable类, 观察者实现Observer接口实现
相关方法有 setChange, clearChange, notifyObservers等
问题:
Observable类限制了复用, 继承的方法拓展性不好
java不支持多继承, 不是接口无法添加自己的实现和原有的API搭配使用, setChanged()等方法的保护级别为protected, 外部无法覆盖, 只能通过继承覆盖
**
被观测者继承 java.util.Observable 类
通知需要先setchange(), 再notifyObservers(arg);
public class WeatherData extends Observable {
private String temp;
public void tempChange(String newTemp) {
this.setTemp(newTemp);
setChanged();
notifyObservers("测试传参");
}
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
}
观察者实现java.util.Observer接口, 持有Observable属性
并在构造方法中将自身注册, 重写update方法接收消息
public class Display1 implements Observer, Display {
Observable observable;
private String disTemp;
public Display1(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof WeatherData) {
WeatherData data = (WeatherData) o;
this.disTemp = data.getTemp();
System.out.println("接收到的参数为: " + (String) arg);
}
}
public String getDisTemp() {
return disTemp;
}
public void setDisTemp(String disTemp) {
this.disTemp = disTemp;
}
@Override
public void display() {
System.out.println("这里是布告板1,现在的温度是: " + this.disTemp);
}
}
**
测试
@Test
public void testStrategy() {
WeatherData weatherData = new WeatherData();
weatherData.setTemp("12度");
Display1 display1 = new Display1(weatherData);
Display2 display2 = new Display2(weatherData);
display1.display();
display2.display();
weatherData.tempChange("20度");
display1.display();
display2.display();
}
结果:
这里是布告板1,现在的温度是: null
这里是布告板2,现在的温度是: null
接收到的参数为: 测试传参
接收到的参数为: 测试传参
这里是布告板1,现在的温度是: 20度
这里是布告板2,现在的温度是: 20度