Java Q&A: 使用Observer模式(转)

发布时间: 2007-05-21 09:44    作者: 未知    来源: 未知    浏览:    评论

Java Q&A: 使用Observer模式

A:我想在自己的Java程序中使用Observer模式。基于此,能否提供某些示例代码来演示如何去做?

Q:正如面向对象编程有助于代码复用一样,设计模式可以促进设计复用。确实,设计模式可以让你复用那些正确的、成熟的设计。但近来,批评设计模式的声音越来越多。批评者指出,缺乏经验的开发者会很容易地掉进 "模式陷阱" 之中。

模式陷阱让缺乏经验的开发者迷失了方向。因而,他们在处理问题时不是去寻找可能存在的最好方案,而把最终目标集中在尽可能地实现更多的设计模式之上。在一些人看来,使用设计模式好象必然会带来良好的设计。按照这个逻辑,只要大量使用设计模式,就必然为你产生一个优秀的设计!然而现实中,这一观点却导致出许多毫无意义的设计--即使这个设计采用了多个设计模式。看来很遗憾,设计模式并不能保证良好的设计。

要想在设计中正确地运用一个设计模式,必须确保三个条件:

1. 弄清你的问题

2. 了解这个模式

3. 理解这个模式如何解决你的问题

首先,最重要的是条件1。如果不能完全地弄清你要解决的问题,何谈运用模式?

还要知道条件2:必须完全了解你想运用的模式。不了解它怎么能运用它?更重要的是,连一个模式做什么都不知道,又如何想到去用它?

最后一点,如果你不能清楚地说出模式将怎样解决你的问题(为什么这个模式合适),那还是放弃它。仅仅为了用模式本身而去用它,就会掉进模式陷阱之中。

我并不是在说提这个问题的读者也一定会掉进模式陷阱。但从提问的表达上来看,它很容易误导一些开发者去理解设计模式。我对这个提问的理解是,这位读者应该清楚自己需要解决的问题,也了解Observer模式,他/她只是不知道如何用Java来实现。

在给出一个Java示例之前,为了有助于其他读者也能理解,先简要介绍一下Observer模式。

简单来说,Observer模式让一个对象(观察者,Observer)去监视另一个对象(目标,Subject);它使得目标和观察者之间建立一种 "发布--订阅"(publish-subscribe )的关系。通过Observer模式,观察者可以向目标登记,表明自己要从目标接收事件。目标需要向观察者通知事件时,只是简单地将事件发给每一个观察者。

例如,有一个基于某种数据模型的电子表格。只要数据模型发生变化,电子表格就需要更新表格单元以及内嵌的图表。这个例子中,目标是数据模型,观察者是表格单元和图表。当观察者接收到数据模型已经变化的通知时,它们就更新自己。

Observer模式的好处是:它解除了观察者和目标之间的耦合关系。目标不需要知道它的观察者的任何信息。相反,目标只是允许观察者订阅事件。当目标产生一个事件时,它简单地将事件传给每一个观察者。

看看下面的Java示例:

public interface Subject {
      public void addObserver( Observer o );
      public void removeObserver( Observer o );
}

上面的代码中,Subject接口定义了两个方法(method),每个Subject都必须实现它们,以使Observer可以在Subject中增加或删除自身。

public interface Observer {
      public void update( Subject o );
}

Observer接口(如上)列出了一个方法(method),每个Observer都必须实现它,以使Subject可以发送更新消息给Observer。

下面看看Subject的一个简单的实现--IntegerDataBag:

import java.util.ArrayList;
import java.util.Iterator;

public class IntegerDataBag implements Subject {

      private ArrayList list = new ArrayList();
      private ArrayList observers = new ArrayList();

      public void add( Integer i ) {
            list.add( i );
            notifyObservers();
      }

      public Iterator iterator() {
            return list.iterator();
      }

      public Integer remove( int index ) {
            if( index < list.size() ) {
                  Integer i = (Integer) list.remove( index );
                  notifyObservers();
                  return i;
            }
            return null;
      }

      public void addObserver( Observer o ) {
            observers.add( o );
      }

      public void removeObserver( Observer o ) {
            observers.remove( o );
      }

      private void notifyObservers() {
            // loop through and notify each observer
            Iterator i = observers.iterator();
            while( i.hasNext() ) {
                  Observer o = ( Observer ) i.next();
                  o.update( this );
            }
      }
}

IntegerDataBag适用于使用Integer的场合。IntegerDataBag也允许Observer增加和删除它们自身。

再看看两个Observer的实现--IntegerAdder和IntegerPrinter:

import java.util.Iterator;

public class IntegerAdder implements Observer {

      private IntegerDataBag bag;

      public IntegerAdder( IntegerDataBag bag ) {
            this.bag = bag;               
            bag.addObserver( this );
      }

      public void update( Subject o ) {
            if( o == bag ) {
                  System.out.println( "The contents of the IntegerDataBag have changed." );
                  int counter = 0;
                  Iterator i = bag.iterator();
                  while( i.hasNext() ) {
                        Integer integer = ( Integer ) i.next();
                        counter+=integer.intValue();
                  }
                  System.out.println( "The new sum of the integers is: " + counter );
            }
      }

}

import java.util.Iterator;

public class IntegerPrinter implements Observer {

      private IntegerDataBag bag;

      public IntegerPrinter( IntegerDataBag bag ) {
            this.bag = bag;               
            bag.addObserver( this );
      }

      public void update( Subject o ) {
            if( o == bag ) {
                  System.out.println( "The contents of the IntegerDataBag have changed." );
                  System.out.println( "The new contents of the IntegerDataBag contains:" );
                  Iterator i = bag.iterator();
                  while( i.hasNext() ) {
                        System.out.println( i.next() );
                  }
            }
      }

}

IntegerAdder和IntegerPrinter将自己作为观察者增加到IntegerDataBag。当IntegerAdder接收到一条更新消息时,它先统计bag中的总数,然后显示结果。同样,当IntegerPrinter接收到一条更新消息时,它打印出bag中的Interger。

下面是一个简单的main(),它使用了上面的几个类:

public class Driver {
      public static void main( String [] args ) {
            Integer i1 = new Integer( 1 ); Integer i2 = new Integer( 2 );
            Integer i3 = new Integer( 3 ); Integer i4 = new Integer( 4 );
            Integer i5 = new Integer( 5 ); Integer i6 = new Integer( 6 );
            Integer i7 = new Integer( 7 ); Integer i8 = new Integer( 8 );
            Integer i9 = new Integer( 9 );

            IntegerDataBag bag = new IntegerDataBag();
            bag.add( i1 ); bag.add( i2 ); bag.add( i3 ); bag.add( i4 );
            bag.add( i5 ); bag.add( i6 ); bag.add( i7 ); bag.add( i8 );

            IntegerAdder adder = new IntegerAdder( bag );
            IntegerPrinter printer = new IntegerPrinter( bag );

            // adder and printer add themselves to the bag

            System.out.println( "About to add another integer to the bag:" );
            bag.add( i9 );
            System.out.println("");
            System.out.println("About to remove an integer from the bag:");
            bag.remove( 0 );
      }
}

运行main,你将看到:

c:\javaworld\java Driver
About to add another integer to the bag:
The contents of the IntegerDataBag have changed.
The new sum of the intergers is: 45
The contents of the IntegerDataBag have changed.
The new contents of the IntegerDataBag contains:
1
2
3
4
5
6
7
8
9

About to remove an integer from the bag:
The contents of the IntegerDataBag have changed.
The new sum of the intergers is: 44
The contents of the IntegerDataBag have changed.
The new contents of the IntegerDataBag contains:
2
3
4
5
6
7
8
9

IntegerDataBag/IntegerAdder/IntegerPrinter是应用Observer模式的一个很简单的例子。Java本身有大量使用Observer模式的例子:AWT/Swing事件模型,还有java.util.Observer和java.util.Observable接口等,都是很好的例子。

TAG

Smile Big Smile Surprise Stick out tongue Wink Sad Tongue Tied Indifferent Crying Embarrassed Cool Angry Angel Devil [8-|] [:#] [:-*] [:^)] [<:o)] [|-)] Yes Beer Left Hug Music Star Time Snail Pizza Automobile Umbrella Computer Storm [mo] [8o|] [^o)] [+o(] [*-)] [8-)] Coffee No Drinks [Z] Right Hug Cake Broken Heart Gift Wilted Flower Movie Dog Idea Sleep Email Travel Paradise
呢称:

加粗 斜体 下划线 链接 图片 代码 邮件地址 引用 列表

最多只能输入100个字符

Tags

SQL 数据库 asp.net C# XML 控件 .NET教程 程序 事件 数据 安全 代码 Server 客户端 验证 数据库专栏 接口 文件 Oracle DataSet 函数 DataGrid 问题 .net return C#语言 JavaScript 服务 IIS 对象 语句 windows 继承 时间 web.config 设计 开发 参数 变量 解决 字符 ADO.net 环境 VB.Net语言 web 异常 工具 服务器 计算 实例 OLEDB Application VB Word WebService insert asp net 安装 记录

精华推荐

更多

精品下载

更多