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

观察者模式

观察者模式又称为订阅—发布模式,在此模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来事件处理系统。

基于事件驱动机制的系统或语言,比如node.js、nio等,不难发现其最终的基础模式就是观察者模式,只是不同的应用场景,也会有各自不同的侧重。


观察者

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);   
    }   
}  

监听器模式
事件源经过事件的封装传给监听器,当事件源触发事件后,监听器接收到事件对象可以回调事件的方法

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));   
           }   
    }   
}  

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...");   
    }   
}  
3、最后定义我们的事件侦听器接口如下

public interface DemoListener extends java.util.EventListener {   
    //EventListener是所有事件侦听器接口必须扩展的标记接口、因为它是无内容的标记接口、   
    //所以事件处理方法由我们自己声明如下:   
    public void handleEvent(DemoEvent dm);   
}
监听器实现类

public class DemoListener1 implements DemoListener {   
       public void handleEvent(DemoEvent de) {   
              System.out.println("Inside listener1...");   
              de.say();//回调   
       }   
} 
4、测试代码
public class TestDemo {   
   DemoSource ds;   
   public TestDemo(){   
      try{   
         ds = new DemoSource();   
         //将监听器在事件源对象中登记:   
         DemoListener1 listener1 = new DemoListener1();   
         ds.addDemoListener(listener1);   
         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();   
    }   
}  

总结
监听器模式是观察者模式的另一种形态,同样基于事件驱动模型。监听器模式更加灵活,可以对不同事件作出相应。但也是付出了系统的复杂性作为代价的,因为我们要为每一个事件源定制一个监听器以及事件,这会增加系统的负担


发布订阅
观察者模式实现发布订阅,可以添加一个调度中心,降低publisher和subscriber的耦合,具体实现中,有两个版本。
1) 拉模式:目标角色在发生变化后,仅仅告诉观察者角色“我变化了”;观察者角色如果想要知道具体的变化细节,则就要自己从目标角色的接口中得到。拉模式是想要就主动表白获取。

2) 推模式:通知你发生变化的同时,通过一个参数将变化的细节传递到观察者角色中去。推模式是管你要不要,先给你啦。
这两种模式的使用,取决于系统设计时的需要。如果目标角色比较复杂,并且观察者角色进行更新时必须得到一些具体变化的信息,则“推模式”比较合适。如果目标角色比较简单,则“拉模式”就很合适啦。

事件和消息的区别
事件本身即是具有特定业务含义的一种固定结构对象,而消息是数据传输过程中的载体。概念上宽泛来讲,事件可以称作是一种消息,而消息不能代替事件。事件反映的是特定的业务状态,比如订单创建、服务调用失败、应用宕机等。
一个事件对象描述的是谁在什么时间做了什么事情,看到这个对象,我们就能知道是发生了什么特定的事情。但是事件对象本身不承载数据传递的职能。
消息中间件实现的是消息的存储,解决的是解耦上下游业务系统。事件处理系统是更多的侧重对事件的分析处理,并驱动业务的进一步扭转。




评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值