您的位置:首页 > 编程语言 > Java开发

java设计模式--观察者模式和事件监听器模式

2013-04-06 13:40 435 查看
文章转载于:http://www.java2000.net/p9452

复习设计模式,看到observer观察者模式,说法是该模式和iterator迭代器模式类似已经被整合进jdk,但是jdk提供了两种接口:

一、java.util.Observer —— 观察者接口 对应:

java.util.Observable ——受查者根类

二、java.util.EventListener —— 事件监听/处理接口 对应:

java.util.EventObject —— 事件(状态)对象根类

研究了一下发现这两种接口的目的、功能其实是一样的(仅在事件模型的结构上有些许差异),先看EventListener事件监听器模式:

1、首要定义事件源对象(事件源相当于单击按钮事件当中的按钮对象、属于被监听者):

查看复制到剪切板打印

public class DemoSource {

private Vector repository = new Vector();//监听自己的监听器队列

public DemoSource(){}

public void addDemoListener(DemoListener dl) {

repository.addElement(dl);

}

public void notifyDemoEvent() {//通知所有的监听器

Enumeration enum = repository.elements();

while(enum.hasMoreElements()) {

DemoListener dl = (DemoListener)enum.nextElement();

dl.handleEvent(new DemoEvent(this));

}

}

}

[Java] view
plaincopy

public class DemoSource {

private Vector repository = new Vector();//监听自己的监听器队列

public DemoSource(){}

public void addDemoListener(DemoListener dl) {

repository.addElement(dl);

}

public void notifyDemoEvent() {//通知所有的监听器

Enumeration enum = repository.elements();

while(enum.hasMoreElements()) {

DemoListener dl = (DemoListener)enum.nextElement();

dl.handleEvent(new DemoEvent(this));

}

}

}

2、其次定义事件(状态)对象(该事件对象包装了事件源对象、作为参数传递给监听器、很薄的一层包装类):

查看复制到剪切板打印

public class DemoEvent extends java.util.EventObject {

public DemoEvent(Object source) {

super(source);//source—事件源对象—如在界面上发生的点击按钮事件中的按钮

//所有 Event 在构造时都引用了对象 "source",在逻辑上认为该对象是最初发生有关 Event 的对象

}

public void say() {

System.out.println("This is say method...");

}

}

[Java] view
plaincopy

public class DemoEvent extends java.util.EventObject {

public DemoEvent(Object source) {

super(source);//source—事件源对象—如在界面上发生的点击按钮事件中的按钮

//所有 Event 在构造时都引用了对象 "source",在逻辑上认为该对象是最初发生有关 Event 的对象

}

public void say() {

System.out.println("This is say method...");

}

}

3、最后定义我们的事件侦听器接口如下:

查看复制到剪切板打印

public interface DemoListener extends java.util.EventListener {

//EventListener是所有事件侦听器接口必须扩展的标记接口、因为它是无内容的标记接口、

//所以事件处理方法由我们自己声明如下:

public void handleEvent(DemoEvent dm);

}

[Java] view
plaincopy

public interface DemoListener extends java.util.EventListener {

//EventListener是所有事件侦听器接口必须扩展的标记接口、因为它是无内容的标记接口、

//所以事件处理方法由我们自己声明如下:

public void handleEvent(DemoEvent dm);

}

4、测试代码

查看复制到剪切板打印

//定义具体的事件监听器:

public class DemoListener1 implements DemoListener {

public void handleEvent(DemoEvent de) {

System.out.println("Inside listener1...");

de.say();//回调

}

}

public class TestDemo {

DemoSource ds;

public TestDemo(){

try{

ds = new DemoSource();

//将监听器在事件源对象中登记:

DemoListener1 l1 = new DemoListener1();

ds.addDemoListener(l1);

ds.addDemoListener(new DemoListener() {

public void handleEvent(DemoEvent event) {

System.out.println("Method come from 匿名类...");

}

});

ds.notifyDemoEvent();//触发事件、通知监听器

}catch(Exception ex) {ex.printStackTrace();}

}

public static void main(String args[]) {

new TestDemo();

}

}

[Java] view
plaincopy

//定义具体的事件监听器:

public class DemoListener1 implements DemoListener {

public void handleEvent(DemoEvent de) {

System.out.println("Inside listener1...");

de.say();//回调

}

}

public class TestDemo {

DemoSource ds;

public TestDemo(){

try{

ds = new DemoSource();

//将监听器在事件源对象中登记:

DemoListener1 l1 = new DemoListener1();

ds.addDemoListener(l1);

ds.addDemoListener(new DemoListener() {

public void handleEvent(DemoEvent event) {

System.out.println("Method come from 匿名类...");

}

});

ds.notifyDemoEvent();//触发事件、通知监听器

}catch(Exception ex) {ex.printStackTrace();}

}

public static void main(String args[]) {

new TestDemo();

}

}

再看Observer观察者模式:

Observer和EventListener的区别仅仅在于它提前声明了事件处理方法:

update(Observable o, Object arg)

Observer模式当中不存在对应EventObject的角色,Observable被观察者就兼具了source事件源和EventObject事件对象两种角色,模型更简洁。

Observable被观察者根类就持有了观察者队列,也定义了类似notifyDemoEvent()的notifyObservers()方法...

除了结构有差异外实在看不出Observer观察者模式和EventListener事件监听/处理模式的不一样!请教二者还有什么差异吗?

回复:

也不能这么说

我看了一下Observer、Observable的jdk源码,Observer接口没什么可说的仅仅是声明了一个update方法而已,相当于我在interface DemoListener extends java.util.EventListener接口中定义的:handleEvent方法。

为什么声明呢?最主要的是Observer模式比较EventListener的不同之处还在于将大部分工作收归Observable根类完成。

我又看了看Observable根类,虽然代码也很短小但是比较精悍,至少要我自己写考虑不了这么全面。好比java2集合,我们自己也能做些hashmap、arraylist、栈、队但是可靠性应该是比不上jdk提供的。

总结一下Observer模式和EventListener的主要不同之处:

一、模型结构不同:EventListener是传统的c/s界面事件模型,分事件源和事件(状态)角色,事件源要经过事件的包装、成为事件的属性之一再传递给事件监听/处理者,这个事件监听者就相当于观察者。我记得好像VB或C#也是这种模型...而Observer模式的模型就简洁多了,没有分事件源和事件,二者合二为一为一个角色:被观察者,从字面语义上也应该这样,另一个是观察者角色。

二、就是我上面说的Observer模式比较EventListener的不同之处还在于将大部分工作收归Observable根类实现了、包括定义监听者队列、通知方法都实现了,我们只要继承、调用和传值就行了。

现在想想可能是EventListener监听机制是从c/s时代就延续下来的,而Observer模式则是和iterator迭代器模式同样被整合进jdk的,所以现在这两种功用存在交叉的api会同时存在。

也贴出来Observer模式演示代码来对比

查看复制到剪切板打印

//观察者

class Watcher implements java.util.Observer {

public void update(java.util.Observable obj, Object arg) {

System.out.println("Update() called, count is "

+ ((Integer) arg).intValue());

}

}

//被观察者

class BeingWatched extends java.util.Observable {

void counter(int period) {

for(; period>=0; period-- ) {

setChanged();

notifyObservers(new Integer(period));

try {

Thread.sleep(100);

} catch( InterruptedException e) {

System.out.println("Sleep interrupeted" );

}

}

}

};

//演示

public class ObserverDemo {

public static void main(String[] args) {

BeingWatched beingWatched = new BeingWatched();//受查者

Watcher watcher = new Watcher();//观察者

beingWatched.addObserver(watcher);

beingWatched.counter(10);

}

}

[Java] view
plaincopy

//观察者

class Watcher implements java.util.Observer {

public void update(java.util.Observable obj, Object arg) {

System.out.println("Update() called, count is "

+ ((Integer) arg).intValue());

}

}

//被观察者

class BeingWatched extends java.util.Observable {

void counter(int period) {

for(; period>=0; period-- ) {

setChanged();

notifyObservers(new Integer(period));

try {

Thread.sleep(100);

} catch( InterruptedException e) {

System.out.println("Sleep interrupeted" );

}

}

}

};

//演示

public class ObserverDemo {

public static void main(String[] args) {

BeingWatched beingWatched = new BeingWatched();//受查者

Watcher watcher = new Watcher();//观察者

beingWatched.addObserver(watcher);

beingWatched.counter(10);

}

}

回复:

查阅了一些相关的东东

原来这两种api可以说都是基于:订阅-发布模式的事件/消息通知模式,二者应该都算是“推”方式吧,就是被监控者将消息通知给所有监控者。

1、订阅:Observable.addObserver;

事件源.addDemoListener(这个方法是自己定义的)。

2、发布:Observable需要两步:setChanged()、notifyObservers(newValue);

事件源.notifyDemoEvent()(这个方法也是自己定义的)。

有人说Observer是设计模式中的皇后,很多系统级实现都是这种方式,我觉得是不是搞混了,因为我看java.util.Observer的api没什么下级接口或实现类。

反倒是相似的java.util.EventListener有大量下级接口和实现类,著名的包括:

java.beans.PropertyChangeListener

javax.servlet.http.HttpSessionListener...

以及java界面api里的很多...

这么看EventListener比Observer应用多得多,我猜想是否是因为EventListener的限制较少、没有规定事件处理方法名、比如HttpSessionListener就根据自己的应用领域定义事件处理方法:

sessionCreated(HttpSessionEvent se) 和

sessionDestroyed(HttpSessionEvent se)

如果用Observer就只能叫update了。

转自:http://blog.csdn.net/playboyb/article/details/5481325
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: