分享

Java SE 观察者模式

 昵称9918558 2012-05-08

观察者模式是设计模式中一种很重要的模式,好多时候它能给人一种自动化的感觉。例如MFC中的回调函数、javaAWTSWING中的组件事件都采用的是这种模型。

那么我们就先来理解一下这种模型的概念及其生存价值:

所谓的观察者模式就是通过模拟人的眼睛,当眼睛发现周围的情况发生改变时,都会给大脑一个通知,告诉大脑所发生的变换,然后大脑就会做出相应的判断、抉择。这样就实现了一种“自动化”。联想一下java中的事件机制,看着都是很奇妙、很玄乎的,总是给人一个自动化的感觉,例如当我们点击一个组件时,就会引发另一个组件的改变或者其它改变,它所利用的就是一种观察者模式。

那么这种模式的生存价值怎样呢,可以理解,我们正常的生活如果缺少了眼睛,那么我们的世界会变得多么的悲催。它的价值也就如同我们的眼睛,它可以为我们的代码添加十足的活力。

废话少说,还是以代码说明问题吧,首先分析一下我们常用的AWT的事件模型。

AWT中所有的事件都是实现了EventListener这个接口,这个接口和AnnotationSerializable接口一样都是一种标记接口。这样做利用了面向对象的多态机制,我们可以定义一个EventListener而指向所有的事件。这个也是所有观察者的总称。

上面的观察者已经了然了,下面就看一下呗观察者了,被观察者比较多,比如容器、组件。。。太多了,就不一一列举了。这儿就拿一个Button作为讲解对象吧。

我们都知道为Button添加事件的方法就是:

Button.addActionListener(new ActionListener()

{

       Public voidactioinPerformed(ActionEvent event)

       {

              //doSomething

}

});

当我们添加添加完事件之后,jdk就会将该事件与相关的组件进行关联,然后进行组件监听。观察其后面的代码,发现要委托给一个java.awt.AWTEventMulticaster的对象进行管理事件。下面我们就简单的了解一下该对象(下面内容请参看帮助文档)。

AWTEventMulticaster 实现对 java.awt.event 包中定义的 AWT 事件的指派,该指派是有效的、线程安全的多路广播事件指派。 

以下实例阐释了如何使用此类:

 public myComponent extends Component {

    ActionListener actionListener = null;

    public synchronized void addActionListener(ActionListener l) {

          actionListener = AWTEventMulticaster.add(actionListener, l);

    }

    public synchronized void removeActionListener(ActionListener l) {

           actionListener =AWTEventMulticaster.remove(actionListener, l);

    }

    public void processEvent(AWTEvent e) {

        // when event occurs which causes "action" semantic

        ActionListener listener = actionListener;

        if (listener != null) {

            listener.actionPerformed(new ActionEvent());

        }

    }

 }

 需要重点注意的是 add  remove 方法的第一个参数,它是维护侦听器的字段。此外,必须将 add  remove 方法的结果分配给维护侦听器的字段。

 

 

当我们将事件和组件进行关联的时候,那么组件是如何的调用事件呢。请看如下源代码:

   protected void processEvent(AWTEvent e) {

       if (e instanceof ActionEvent) {

           processActionEvent((ActionEvent)e);

           return;

       }

       super.processEvent(e);

    }

当获取一个事件的时候,会先进行事件的类型判断,然后根据其类型做出相应的抉择,我们此刻要关心的是ActionPerformed方法的调用,那么我们就要关注processActionEvent这个方法。

    protected void processActionEvent(ActionEvente) {

       ActionListener listener = actionListener;

       if (listener != null) {

           listener.actionPerformed(e);

       }

    }

此刻我们定义的方法就会得到调用。

 

 

当我们分析完一个Button的事件调用机制后,我们来写一个自己的观察者模式。

还是先看一下观察者模式的UML类图吧(刚刚开始学UML



下面看一下观察者模式的模拟代码:

//观察者接口

package dong.application.observePattern;

/**

 * 观察者接口

* @author HS

*/

public interface Watcher

{

       /**

        * 更新操作,当观察者发现实体情况有变化时,实体就会调用该函数进行相应的操作

        */

       publicvoid update();

}

 

//观察者的具体实现类

package dong.application.observePattern;

/**

 * 具体的观察者

 *@author HS

*/

public class ConcreteWatcher implementsWatcher

{

       @Override

       publicvoid update()

       {

              System.out.println("updating...");

       }

}

 

 

//实体接口

package dong.application.observePattern;

/**

 * 观察实体(被观察者)的接口,这样的定义有利于多态的实现,对用户提供统一的接口

* @author HS

*/

public interface Watched

{

       /**

        * 增加一个观察者

        * 

        * @param watcher

        *           要增加的观察者

        */

       publicvoid addWatcher(Watcher watcher);

       /**

        * 移除一个观察者

        * @param watcher

        *           要移除的观察者

        */

       publicvoid removeWatcher(Watcher watcher);

 

       /**

        * 当某一个发生时,会通知所有的观察者(此函数就是用来通知所有的观察者)

        */

       publicvoid notifyAllWatcher();

}

 

//具体实体接口

package dong.application.observePattern;

 

import java.util.ArrayList;

import java.util.List;

 

/**

 * 具体的实体

 * 

 *@author HS

 * 

 */

 

public class ConcreteWatched implementsWatched

{

       /**

        * 观察者列表

        */

       privateList<Watcher> watchers = new ArrayList<Watcher>();

 

       @Override

       publicvoid addWatcher(Watcher watcher)

       {

              watchers.add(watcher);

       }

 

       @Override

       publicvoid removeWatcher(Watcher watcher)

       {

              watchers.remove(watcher);

       }

       @Override

       publicvoid notifyAllWatcher()

       {

              for(Watcher watcher : watchers)

              {

                     watcher.update();

              }

       }

}

 

//客户端测试

package dong.application.observePattern;

 

public class ObserveTest

{

       publicstatic void main(String[] args)

       {

              //定义三个观察者

              Watcherwatcher1 = new ConcreteWatcher()

              {

                     //模拟AWT中的定义方式

                     @Override

                     publicvoid update()

                     {

                            System.out.println("iam observer 1");

                     }

              };

              

              Watcherwatcher3 = new ConcreteWatcher();

              //定义一个实体

              Watchedwatched = new ConcreteWatched();

              //为实体注册观察者

              watched.addWatcher(watcher1);

              watched.addWatcher(newWatcher()

              {

                     @Override

                     publicvoid update()

                     {

                            System.out.println("iam observe 2");

                     }

              });

 

              watched.addWatcher(watcher3);

 

              //模拟当观察实体发生变化时,出发观察者

              watched.notifyAllWatcher();

       }

}

 

//execute Result

i amobserver 1

i amobserve 2

updating...

 

看完了代码,估计也不需要过多的解释了,如果在多分析一下C++(回调机制)、Java事件监听机制等的观察者模式利用方法会对我们的帮助更大。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多