前言
观察者模式定义了一种一对多的关系,其中一个对象(称为观察者)可以订阅另一个对象(称为主题)的更改,并在主题发生更改时自动接收通知。这样,观察者对象就可以根据主题的状态来更新自己的状态。这种模式可以让主题和观察者之间松耦合,从而使两者独立变化。
角色
- 观察者:观察者是一个接口或抽象类,定义了一个更新自己的方法,当主题状态改变时,观察者需要实现这个方法来更新自己的状态。
- 具体观察者:具体观察者是观察者的实现类,在具体观察者中实现更新自己的方法,以便在主题状态改变时更新自己的状态。
- 主题:主题是一个接口或抽象类,定义了一些方法来管理观察者的生命周期,如注册、移除和通知观察者。
- 具体主题:具体主题是主题的实现类,在具体主题中实现了主题的方法,以便管理。
代码示例
观察者
public interface Observer {
void update(Subject subject);
}
具体观察者
public class ConcreteObserver implements Observer{
private String name;
public ConcreteObserver(String name){
this.name = name;
}
@Override
public void update(Subject subject) {
//更新状态
System.out.println(this.name + "收到通知");
}
主题
public interface Subject {
/**
* 注册观察者
* @param observer
*/
void registerObserver(Observer observer);
/**
* 移除观察者
* @param observer
*/
void removeObserver(Observer observer);
/**
* 通知所有观察者
*/
void notifyObservers();
}
具体主题
public class ConcreteSubject implements Subject{
List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(this);
}
}
}
测试
public class Demo {
public static void main(String[] args) {
// 创建一个主题对象
Subject subject = new ConcreteSubject();
// 创建两个观察者对象
Observer observer1 = new ConcreteObserver("观察者1号");
Observer observer2 = new ConcreteObserver("观察者2号");
// 将观察者注册到主题中
subject.registerObserver(observer1);
subject.registerObserver(observer2);
//发送通知
subject.notifyObservers();
}
}
输出
优缺点
优点
- 实现了观察者和被观察者之间的松耦合,观察者可以通过接口接收通知,而不用关心被观察者的实现细节。
- 支持一个被观察者对象同时被多个观察者观察,并且支持观察者动态地添加和删除。
缺点
- 当被观察者对象发生变化时,需要通知所有观察者,这可能会带来一定的性能问题,特别是在观察者数量比较多的情况下。
- 如果观察者和被观察者之间的依赖关系过于紧密,观察者可能会变得臃肿,导致代码的复杂度和可维护性降低