观察者模式很好理解,简单来说就是:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。
手工创建Observer模式
- 创建观察者接口
public interface Observer {
void update();
}
- 创建Publisher接口
public interface Publisher {
void add(Observer observer);
void delete(Observer observer);
void notifyObservers();
void operation();
}
- 基本功能实现(为了线程安全我们可以选择Vector)
import java.util.ArrayList;
import java.util.List;
public abstract class PublisherAdapter implements Publisher {
private List<Observer> observers = new ArrayList<Observer>();
@Override
public void add(Observer observer) {
observers.add(observer);
}
@Override
public void delete(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers)
observer.update();
}
}
- 实现类
public class PublisherImpl extends PublisherAdapter {
@Override
public void operation() {
System.out.println("this is operation");
notifyObservers();
}
}
- 测试类
public class Main {
public static void main(String[] args) {
Publisher impl = new PublisherImpl();
impl.add(new Observer() {
@Override
public void update() {
System.out.println("observer 1 receive");
}
});
impl.add(new Observer() {
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("observer 2 receive");
}
});
impl.operation();
}
}
测试结果:
this is operation
observer 1 receive
observer 2 receive
使用java.util.Observer接口
这个接口只定义了一个方法:
update()
。当被观察者(Observable
)对象的状态发生变化时,这个方法就会被调用。通过调用被观察者对象的notifyObservers()
方法通知所有的观察对象。
- 定义被观察者
被观察者类都是java.util.Observable
类的子类
import java.util.Observable;
public class Publisher extends Observable {
public void operation() {
System.out.println("this is operation");
this.setChanged();
this.notifyObservers();
}
}
- 测试
import java.util.Observable;
import java.util.Observer;
public class Main {
public static void main(String[] args) {
Publisher publisher = new Publisher();
publisher.addObserver(new Observer() {
@Override
public void update(Observable o, Object arg) {
System.out.println("observer 1 receive");
}
});
publisher.addObserver(new Observer() {
@Override
public void update(Observable o, Object arg) {
System.out.println("observer 2 receive");
}
});
publisher.operation();
}
}
当然,若要获得被观察者的信息,可以将Observable o转换为Publisher类型:
Publisher p = (Publisher)o;
分析Observer与Observable
如前所述,Observer接口只定义了一个方法:update()。当被观察者对象的状态发生变化时,这个方法就会被调用。
java.util.Observer
接口定义如下:
package java.util;
public interface Observer {
void update(Observable o, Object arg);
}
被观察者类都是
java.util.Observable
类的子类。java.util.Observable
提供公开的方法支持观察者对象,这些方法中有两个非常重要:
setChanged()
:被调用之后会设置一个内部标记变量,代表被观察者对象的状态发生了变化;
notifyObservers()
:这个方法被调用时,会调用所有登记过的观察者对象的update()
方法。
附源码
package java.util;
public class Observable {
private boolean changed = false;
private Vector obs;
public Observable() {
obs = new Vector();
}
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i >= 0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
可用如下类图表示(图片来自于网络):
总结
观察者模式优点:
- 观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
- 观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知。
观察者模式缺点:
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。
- 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。
代码在这里。