概念
定义了一种一对多的依赖关系,让多个观察者对象同时监听某个主题对象。这个主题对象在转换状态时,会通知所有的观察者对象,使它们能够自动更新自己
结构
抽象观察者角色:定义了一个更新接口,使主题角色更改通知时更新自己
具体观察者角色:实现抽象观察者角色定义的更新接口,以便在主题角色更改通知时更新自己的状态
抽象主题角色:抽象主题角色将所有观察者对象保存在一个集合中,每个主题都可以拥有若干数量的观察者。抽象主题角色提供一个接口,可以增加和删除观察者角色
具体主题角色:具体主题角色将有关状态存入具体观察者对象,在具体主题角色的内部状态发生改变时,给所有注册过的观察者发送通知
示例
目标:如气象站检测温度,当发现有变化时,通知跟其合作的天气预报台更新温度
抽象观察者角色
package 设计模式.行为型模式.观察者模式;
/**
* 抽象观察者角色
*/
public abstract class Observer {
/**
* 更新
*/
abstract void change(double temperature);
}
具体观察者角色一
package 设计模式.行为型模式.观察者模式;
/**
* 彩虹天气:具体主题角色
*/
public class RainbowWeather extends Observer {
/**
* 更新
*/
@Override
void change(double temperature) {
System.out.println("彩虹天气:当前温度为" + temperature);
}
}
具体观察者角色二
package 设计模式.行为型模式.观察者模式;
/**
* 堆代码 duidaima.com
* 墨迹天气:具体主题角色
*/
public class MojiWeather extends Observer {
/**
* 更新
*/
@Override
void change(double temperature) {
System.out.println("墨迹天气:当前温度为" + temperature);
}
}
抽象主题角色
package 设计模式.行为型模式.观察者模式;
/**
* 抽象主题角色
*/
public abstract class Subject {
/**
* 注册观察者
*/
abstract void registerObserver(Observer user);
/**
* 移除观察者
*/
abstract void removeObserver(Observer user);
/**
* 通知观察者
*/
abstract void notifyObserver();
}
具体主题角色
package 设计模式.行为型模式.观察者模式;
import java.util.ArrayList;
import java.util.List;
/**
* 气象站:具体主题角色
*/
public class WeatherStation extends Subject {
/** 保存的观察者角色对象 */
private List<Observer> userList = new ArrayList<>();
/** 温度 */
private double temperature;
/**
* 设置温度
*/
void setTemperature(double temperature) {
this.temperature = temperature;
}
/**
* 注册观察者
*/
@Override
void registerObserver(Observer user) {
userList.add(user);
}
/**
* 移除观察者
*/
@Override
void removeObserver(Observer user) {
userList.remove(user);
}
/**
* 通知观察者
*/
@Override
void notifyObserver() {
for (Observer user : userList) {
user.change(this.temperature);
}
}
}
测试类
package 设计模式.行为型模式.观察者模式;
/**
* 测试类
*/
public class Demo {
public static void main(String[] args) {
// 创建气象台的主题角色对象
WeatherStation subject = new WeatherStation();
// 添加观察者角色对象
subject.registerObserver(new RainbowWeather());
subject.registerObserver(new MojiWeather());
// 更新温度
subject.setTemperature(31.2);
// 通知观察者更新
subject.notifyObserver();
}
}
优缺点
优点
1.降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系
2.被观察者发送通知、所有注册的观察者都会收到信息【可以实现广播机制】
缺点
1.如果观察者非常多,那么所有的观察者收到被观察者发送的通知会耗时
2.如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,导致系统崩溃
应用场景
1.对象之间存在一对多关系,一个对象的状态发生改变会影响其他对象时,可以使用观察者模式
2.当一个抽象模型有两个方面,其中一个方面依赖于另一个方面时,可以使用观察者模式