代码如下:
package com.observer;
import java.util.Vector;
/**
* @author nidayu
* @Description: 观察者模式
* @date 2015/9/19
*/
abstract class Subject {
private Vector<Observer> obs = new Vector<Observer>();
public void addObserver(Observer obs){
this.obs.add(obs);
}
public void delObserver(Observer obs){
this.obs.remove(obs);
}
protected void notifyObserver(){
for(Observer o: obs){
o.update();
}
}
public abstract void doSomething();
}
//被观察者
class ConcreteSubject extends Subject {
public void doSomething(){
System.out.println("被观察者事件发生");
this.notifyObserver();
}
}
//观察者接口
interface Observer {
public void update();
}
//观察者1
class ConcreteObserver1 implements Observer {
public void update() {
System.out.println("观察者1收到信息,并进行处理。");
}
}
//观察者2
class ConcreteObserver2 implements Observer {
public void update() {
System.out.println("观察者2收到信息,并进行处理。");
}
}
public class Client {
public static void main(String[] args){
Subject sub = new ConcreteSubject();
Observer o1 = new ConcreteObserver1();
Observer o2 = new ConcreteObserver2();
sub.addObserver(o1); //添加观察者1
sub.addObserver(o2); //添加观察者2
// sub.delObserver(o2);
sub.doSomething();
}
}
运行结果:
被观察者事件发生
观察者1收到信息,并进行处理。
观察者2收到信息,并进行处理。
通过运行结果可以看到,我们只是调用了Subject的方法,但同时两个观察者相关的方法都被同时调用了。仔细看下代码,其实很简单,无非就是在Subject类中关联一下Observer类,并在doSomething方法中遍历一下Observer的update方法就行了。
使用Vector存放观察者的原因是因为Vector是线程安全的,List是线程不安全的。
观察者模式的优点
观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,这样,对于两者来说都比较容易进行扩展。
观察者模式是一种常用的触发机制,它形成一条触发链,依次对各个观察者的方法进行处理。但同时,这也算是观察者模式一个缺点,由于是链式触发,当观察者比较多的时候,性能问题是比较令人担忧的。并且,在链式结构中,比较容易出现循环引用的错误,造成系统假死。
总结
java语言中,有一个接口Observer,以及它的实现类Observable,对观察者角色常进行了实现。我们可以在jdk的api文档具体查看这两个类的使用方法。
做过VC++、javascript DOM或者AWT开发的朋友都对它们的事件处理感到神奇,了解了观察者模式,就对事件处理机制的原理有了一定的了解了。如果要设计一个事件触发处理机制的功能,使用观察者模式是一个不错的选择,AWT中的事件处理DEM(委派事件模型Delegation Event Model)就是使用观察者模式实现的。