一、定义
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
观察者模式是一种对象行为型模式。
二、使用场景
当一个对象的改变(名词)需要改变(动词)其他对象的时候。
观察者模式可以解决什么问题:
1、应该定义对象间一对多的依赖关系,而不使对象紧密耦合。(达到依赖关系,又不紧耦合)
2、应该确保一个对象改变时,无限制的依赖对象自动更新。
3、应该一个对象可以通知无限制的其他对象。
三、角色分析
抽象主题(Subject): 定义了被观察者常用的方法,订阅(attach)、取消订阅(detach)和通知(notify)功能
具体主题(ConcreteSubject):实现抽象主题定义的方法,通过attach和detach方法维护一个观察者的集合,当自己维护的状态(state)改变时通知(notify)所有观察者
抽象观察者(Observer):定义更新自己的方法
具体观察者(ConcreteObserver):实现更新自己的的方法
四、代码示例
代码示例就使用上面说过的那个例子,员工集体开小差,前台小妹负责在老板回来的时候通知所有人。
首先,前台妹妹是具体主题角色,员工是具体观察者角色。其次,前台妹妹维护着观察者集合,在老板回来了这个状态上通知所有观察者;观察者在前台妹妹通知之后执行自己的更新方法,该干嘛干嘛。
抽象主题:
public interface Observable {
public void attach(Observer observer);
public void detach(Observer observer);
public void notifyObservers();
}
前台妹妹(具体主题即被观察者):
public class Receptionist implements Observable {
private String state = "老板出去了";
private ArrayList<Observer> observers = new ArrayList<>();
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
System.out.println(state);
}
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
observers.forEach(observer -> observer.update());
}
}
看NBA员工观察者:
public class NBAObserver implements Observer{
@Override
public void update() {
System.out.println("正在看NBA直播的关掉NBA直播,工作");
}
}
炒股员工观察者:
public class StockObserver implements Observer {
@Override
public void update() {
System.out.println("正在炒股的关闭股市面板,工作");
}
}
观察者模式测试类:
public class ObserverTest {
public static void main(String[] args) {
Receptionist mm = new Receptionist();
Observer nba = new NBAObserver();
Observer stock = new StockObserver();
mm.attach(nba);
mm.attach(stock);
// mm看到老板回来了
mm.setState("老板回来了");
// 通知已经订阅的员工
mm.notifyObservers();
}
}
测试结果:
五、优缺点
- 优点
满足了当一个对象的改变需要改变其他对象这个条件的前提下,实现了松耦合。
符合开闭原则,继承抽象主题添加被观察者,继承抽象观察者添加观察者。
- 缺点
如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
总结
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。