Design Pattern [5] —— 观察者模式 Observer / 发布订阅模式
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新(广播)。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
我的Github里有源码,可以clone下来自己跑下:https://github.com/Yang2199/Design-Pattern/tree/master/src
例子:
发布者:
import java.util.ArrayList;
import java.util.List;
public class Subject {
private List<Observer> observers
= new ArrayList<Observer>();
private int state;
public int getState() {
return state;
}
public void setState(int state) { //改变发布的值
this.state = state;
System.out.println("发布 =====>> 十进制数: " + this.state);
notifyAllObservers();
}
public void attach(Observer observer){ //新增订阅
observers.add(observer);
}
public void detach(Observer observer){ //退订
observers.remove(observer);
}
public void notifyAllObservers(){ //通知所有观察者
for (Observer observer : observers) {
observer.update();
}
System.out.println("========================");
}
}
订阅者-抽象类:
public abstract class Observer {
protected Subject subject;
public abstract void update();
public abstract void detach();
}
下面写3个订阅者实现类:
1)二进制观察者:
public class BinaryObserver extends Observer{ public BinaryObserver(Subject subject){ this.subject = subject; this.subject.attach(this); //构造的时候同时增加到观察者队列中 System.out.println("新增订阅 => 二进制 观察者"); } @Override public void update() { System.out.println( "二进制-观察者: " + Integer.toBinaryString( subject.getState() ) ); } @Override public void detach() { this.subject.detach(this); System.out.println("退订 => 二进制 观察者"); } }
2)八进制观察者:
public class OctalObserver extends Observer{ public OctalObserver(Subject subject){ this.subject = subject; this.subject.attach(this); System.out.println("新增订阅 => 八进制 观察者"); } @Override public void update() { System.out.println( "八进制-观察者: " + Integer.toOctalString( subject.getState() ) ); } @Override public void detach() { this.subject.detach(this); System.out.println("退订 => 八进制 观察者"); } }
3)十六进制观察者:
public class OctalObserver extends Observer{ public OctalObserver(Subject subject){ this.subject = subject; this.subject.attach(this); System.out.println("新增订阅 => 八进制 观察者"); } @Override public void update() { System.out.println( "八进制-观察者: " + Integer.toOctalString( subject.getState() ) ); } @Override public void detach() { this.subject.detach(this); System.out.println("退订 => 八进制 观察者"); } }
Test类:
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
HexaObserver hexaObserver = new HexaObserver(subject);
BinaryObserver binaryObserver = new BinaryObserver(subject);
subject.setState(15);//发布 广播
OctalObserver octalObserver = new OctalObserver(subject);//新增 八进制观察者
subject.setState(10);//发布 广播
hexaObserver.detach();//十六进制观察者 退订
subject.setState(7);//发布 广播
}
}
结果:
类图: