观察者模式
什么是观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
优点:
1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。
缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
公众号 实例UML图
Observable 被观察者
直接使用java内置的Observable类
里面有一系列方法:
1. addObserver 添加观察员
2. deleteObserver 删除观察员
3. notifyObservers 通知观察员
4. notifyObservers(Observer) 通知某个观察员
5. deleteObservers 删除所有观察员
6. setChangeed 改变信号
WeatherData 具体被观察者
具体被观察者要点:
1. 需要一个集合去存放 观察者
2. 继承Observable
3. 拥有一个修改数据的方法setMeasurements
public class WeatherData extends Observable{
/**
*具体的Observable中会有
* add
* delete
* notify方法
*/
//内置一个存储集合
private List<Weather> weathers = new Vector<>();
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {}
/**
* 数据修改 并且通知
*/
public void measurementsChanged(){
//调用notifyObservers 之前需要先 修改指示状态。 change = true
setChanged();
//修改的次数计数器
count++;
//notifyObservers() 传送数据对象,这代表我们是 “拉”
notifyObservers();
}
public void setMeasurements(float temperature,float humidity,float pressure){
Weather weather = new Weather(temperature, humidity, pressure);
weathers.add(weather);
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
/**
* 通过这些方法 观察者会利用他们去拉取 获得WeatherData的状态
*/
public float getTemperature() {
return temperature;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
@Override
public List<Weather> getWeathers() {
return weathers;
}
@Override
public Integer getCountObservers() {
return count;
}
}
Observer 观察者接口
被观察者对 观察者接口 进行组合
public interface Observer {
void update(Observable o, Object arg);
}
当调用Observable的notifyObservers方法时,进行调用update更新消息。
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
DisplayElement接口 对观察者的行为进行扩展
public interface DisplayElement {
public void display();
}
GeneralDisplay 具体观察者
使得具体观察者去实现 观察者接口 和 扩展接口
并且对Observable被观察者进行组合
public class GeneralDisplay implements Observer, DisplayElement {
Observable observable;
private float temperature;
private float humidity;
public GeneralDisplay(Observable observable){
this.observable = observable;
observable.addObserver(this);
}
@Override
public void display() {
System.out.println("General平台 ↓ \n温度为:"+temperature +" , 湿度为: "+humidity);
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof WeatherData){
WeatherData weatherData = (WeatherData) o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
}
测试类
public static void main(String[] args) {
//公众号
WeatherData weatherData = new WeatherData();
//个人公众号
new GeneralDisplay(weatherData);
new SpecialDisplay(weatherData);
//进行更新信息
weatherData.setMeasurements(30,60,66);
Integer countObservers = weatherData.getCountObservers();
System.out.println("修改数据次数为:"+countObservers);
List<Weather> weathers = weatherData.getWeathers();
System.out.println("以往数据为:"+weathers);
int i = weatherData.countObservers();
System.out.println("平台数为:"+i);
}
随之而来的问题
Java内置对象 Observable是类,这违反了
面向接口编程
的原则,限制了他的复用和使用。
并且其中setChange方法是protected,这意味的你必须继承Observable类,但是Java中不支持类的多继承,这违反了第二个设计原则“多用组合,少用继承
”
如何解决?
1. 我们自己去实现一套观察者模式。
2.扩展
Observable类。
如何扩展 加一层
(这是我的想法,不对可以指出)
我的理解而言如果要使用 java内置对象Observable的话
我会去尝试加一层
public abstract class ObservableAbstract extends Observable {
/**
* @Author JMWANG
* @Description 如果使用还需要一个外置 的 ArrayList集合 在子类中写
*/
public abstract List<Weather> getWeathers();
//计数器专门记录 数据修改次数
public int count;
public abstract Integer getCountObservers();
}
我让 具体观察者直接继承我的抽象类ObservableAbstract
我设计抽象类ObservableAbstract 就是为了进行扩展,这的确无法解决以上的问题,但是我可以使用扩展
,去进行功能的扩展。
又或者我会在 观察者接口下 继续
加层
实现多功能