定义
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
例:我们以新闻机构接收到新闻而后通知各个频道为例。那么新闻机构就是被观察对象,各个频道就是观察者。
实现方式
1、一般模式
① 创建Subject类
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;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
}
② 创建Observer类
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
③ 创建实体观察者类
public class BinaryObserver extends Observer{
public BinaryObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Binary String: "
+ Integer.toBinaryString( subject.getState() ) );
}
}
public class OctalObserver extends Observer{
public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Octal String: "
+ Integer.toOctalString( subject.getState() ) );
}
}
④ 主方法
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}
⑤ 运行结果
First state change: 15
Octal String: 17
Binary String: 1111
Second state change: 10
Octal String: 12
Binary String: 1010
这个例子是参考菜鸟教程,总结得很详细。
2、实现PropertyChangeListener接口
① 创建被观察者
public class Subject {
private int state;
private String message="0";
private PropertyChangeSupport support;
public Subject() {
// TODO Auto-generated constructor stub
support=new PropertyChangeSupport(this);
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyTo(String.valueOf(state));
}
public void addPropertyChangeListener(PropertyChangeListener pcl) {
support.addPropertyChangeListener(pcl);
}
public void removePropertyChangeListener(PropertyChangeListener pcl) {
support.removePropertyChangeListener(pcl);
}
public void notifyTo(String value) {
support.firePropertyChange("",message,value);
}
}
② 创建观察者
public class BinaryObserver implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// TODO Auto-generated method stub
System.out.println( "值更新为 "+evt.getNewValue());
}
}
③ 主方法
public class MyObserver {
public static void main(String[] args) {
Subject subject=new Subject();
BinaryObserver binaryObserver=new BinaryObserver();
subject.addPropertyChangeListener(binaryObserver);
subject.setState(10);
subject.setState(15);
}
}
④ 运行结果
值更新为 10
值更新为 15
这个观察者类就写了一个,懒得写第二个了。
观察者模式我们用图表达出来就是这个样子的
很形象吧!
应用场景
- 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
- 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要被改变。
- 当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之,不希望这些对象是紧密耦合的。
就像报社和订报纸的人
发Email给用户
优缺点
优点
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。
缺点
在应用观察者模式时需要考虑一下开发小路问题,程序中包括一个被观察者和多个被观察者,开发和调试比较复杂,而且Java中的消息的通知默认是顺序执行的,一个观察者的卡顿会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。 [2]