java 观察者模式

模式动机
    建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。
模式定义
    观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式。观察者模式是一种对象行为型模式。

模式分析
    观察者模式描述了如何建立对象与对象之间的依赖关系,如何构造满足这种需求的系统。这一模式中的关键对象是观察目标和观察者,一个目标可以有任意数目的与之相依赖的观察者,一旦目标的状态发生改变,所有的观察者都将得到通知。作为对这个通知的响应,每个观察者都将即时更新自己的状态,以与目标状态同步,这种交互也称为发布-订阅(publish-subscribe)。目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅它并接收通知。
观察者模式顺序图如下所示:
模式应用
(1) JDK1.1版本及以后的各个版本中,事件处理模型采用基于观察者模式的委派事件模型(Delegation Event Model, DEM)。
在DEM中,事件的发布者称为事件源(Event Source),而订阅者叫做事件监听器(Event Listener),在这个过程中还可以通过事件对象(Event Object)来传递与事件相关的信息,可以在事件监听者的实现类中实现事件处理,因此事件监听对象又可以称为事件处理对象。
事件源对象、事件监听对象(事件处理对象)和事件对象构成了Java事件处理模型的三要素。
(2) 除了AWT中的事件处理之外,Java语言解析XML的技术SAX2以及Servlet技术的事件处理机制都基于DEM,它们都是观察者模式的应用。
(3) 观察者模式在软件开发中应用非常广泛,如某电子商务网站可以在执行发送操作后给用户多个发送商品打折信息,某团队战斗游戏中某队友牺牲将给所有成员提示等等,凡是涉及到一对一或者一对多的对象交互场景都可以使用观察者模式。 
Java语言提供的对观察者模式的支持
    在java.util.Observable类中,已经实现了主要的功能,如增加观察者,删除观察者和通知观察者,我们可以直接通过继承Observable使用这些功能。
    java.util.Observer接口是观察者接口,它的update方法会在java.util.Observable中的notifyObservers方法中被回调,以获得最新的状态变化。通常在观察者模式中,Observer接口就是我们程序的核型扩展对象,具体业务逻辑会被封装在update方法中。
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(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 interface Observer {      
    void update(Observable o, Object arg);       
}    
     
public class JMSObserver implements Observer{          
    public void update(Observable o, Object arg) {      
        System.out.println("发送消息给jms服务器的观察者已经被执行");      
    }      
}     
public class Subject extends Observable{      
          
    /**    
     * 业务方法,一旦执行某个操作,则通知观察者,在队列模式中,其实就是当消息被添加到队列的时候,添加进队方法里面调用了通知方法。    
     */     
    public void doBusiness(){      
        if (true) {      
            super.setChanged();      
        }      
        notifyObservers("现在还没有的参数");      
    }      
     
          
    public static void main(String [] args) {      
        //创建一个被观察者      
        Subject subject = new Subject();      
              
        //创建观察者      
        Observer jmsObserver = new JMSObserver();      
              
        //把两个观察者加到被观察者列表中        
        subject.addObserver(jmsObserver);      
              
        //执行业务操作      
        subject.doBusiness();      
    }      
}