观察者模式(发布-订阅模式)
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
拥有一些值得关注的状态的对象通常被称为目标,由于它要将自身的状态改变通知给其他对象,我们也将其称为发布者(publisher)。所有希望关注发布者状态变化的其他对象被称为订阅者(subscribers)。
观察者模式建议你为发布者类添加订阅机制,让每个对象都能订阅或取消订阅发布者事件流。不要害怕!这并不像听上去那么复杂。实际上,该机制包括 1)一个用于存储订阅者对象引用的列表成员变量;2)几个用于添加或删除该列表中订阅者的公有方法。
例子 (发布-订阅)
public interface Observer {
Publisher publisher = null;
public void update();
}
public class Observer1 implements Observer {
private Publisher publisher;
public Observer1(Publisher p) {
this.publisher = p;
this.publisher.addObserver(this);
}
public void update(){
System.out.println(Integer.toBinaryString(this.publisher.getState()));
}
}
import java.util.ArrayList;
import java.util.List;
public class Publisher {
private List<Observer> observers = new ArrayList<Observer>();
private int state;
public void addObserver(Observer ob){
observers.add(ob);
}
public void notifyAllObserver(){
for(Observer observer: observers) {
observer.update();
}
}
public int getState(){
return this.state;
}
public void setState(int state){
this.state = state;
this.notifyAllObserver();
}
}
public class Demo {
public static void main(String[] args) {
Publisher publisher = new Publisher();
new Observer1(publisher);
new Observer2(publisher);
new Observer3(publisher);
System.out.println("First state change: 15");
publisher.setState(15);
System.out.println("Second state change: 10");
publisher.setState(10);
}
}
总结
-
优点:
1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。 -
缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。 -
使用场景:
1、一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
2、一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
3、一个对象必须通知其他对象,而并不知道这些对象是谁。
4、需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。 -
注意事项:
1、JAVA 中已经有了对观察者模式的支持类。
2、避免循环引用。
3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。