Java监听器模式和观察者模式区别

一、监听器模式

监听器的使用比较依赖系统框架,个人设计的往往只是一个事件回调而已。比如Windows系统里的鼠标点击事件回调,有过Win32编程经验的同学就知道,开发人员往往只需要写各种事件的回调函数接口,至于这个事件被用户触发后怎么调用到事件回调函数的这个过程开发人员是不知道的,这是个系统级别的处理,往往对开发人员透明。而对于应用框架设计者而言(如Spring),如果涉及到了监听器,那么功能也是比较简单的,在某个时机会产生事件对象,然后调用监听器的事件处理方法(事件作为参数),就这个过程,也就是说,应用框架决定了事件的触发和调用事件处理方法,应用框架使用者(Web工程师)只需要实现一个事件处理方法即可。这里的事件往往就是应用层次的,完全能掌控在应用框架设计者手里。而上面Win32监听事件而言,事件是在操作系统设计者手里,应用开发者只用写事件处理回调即可。

Java中的事件处理是对系统事件进行了一个封装,你可以使用他这一套事件体系进行针对使用系统特性的软件开发,比如图形界面程序,里面的鼠标点击等事件。而对于服务端程序开发,你不会使用到Java提供的这些事件,所以事件往往是应用层次自定义的事件,事件产生和调用事件处理函数也是应用软件自己处理的事情,这个时候,使用到的Java事件机制往往只是借用了他的接口而已。下面举个简单的例子:

public class MyEvent extends EventObject {
    /**
     * 一般应用框架内部实现,无需开发者创建
     * @param source 包含事件所需信息的对象
     */
    public MyEvent(Object source) {
        super(source);
    }
}

/**
 * 监听器,变化处理者
 */
public class MyListener implements EventListener {
    /**
     * 一般有开发者继承实现,自定义事件处理函数
     * @param e 事件
     */
    void onEvent(EventObject e) {
        System.out.println("event come");
    }
}

public class TestListener {
    public static void main(String[] args) {
        // 一般应用启动时生成监听器,需要自己继承实现监听器处理方法
        MyListener listener = new MyListener();
        // 应用框架在合适时机生成事件对象,一般无需开发者实现
        MyEvent event = new MyEvent("some useful info");
        // 应用框架在事件生成后调用事件回调函数,调用时机由应用框架处理
        listener.onEvent(event);
    }
}

看到上面的代码,是否有脱裤子放屁的嫌疑?不能过于片面的去看,因为Java事件监听体系多半是为了操作系统预设事件服务的,你现在需要自定义事件且完全抛弃了预设事件,那肯定只能使用2个接口而已。监听器模式难在监听器的注册,注册是需要把监听器和事件匹配起来,等到事件产生时,分发给对应的一个或多个监听器。在Spring中,监听器的使用比较简单,因为他的每一个监听器都是个性化定制的,也就是监听器本身语义就只代表一个事件,所以使用起来很简单,你只需要继承某个监听器,这个监听器已经明确的告诉你会在框架做什么操作时调用监听器的事件处理函数。

二、观察者模式

Java中内置了观察者模式的类,应用开发者可以直接使用,java.util.Observable和java.util.Observer就可以让你简单的使用观察者模式了,不过可惜的是,从JDK9开始,他俩就被废弃了,那么你使用时就需要谨慎了,这里我们还是来看看他们怎么使用:

/**
 * 通常是业务对象继承 Observable,被观察者,目标对象,触发变化的源头
 */
public class MyObservable extends Observable {

    /**
     * 被观察者/目标对象
     * @param msg 想要给观察者的信息对象
     */
    public void sendInfo(String msg){
        // protected方法,不能由对象调用
        this.setChanged();
        this.notifyObservers(msg);
    }
}

/**
 * 观察者,变化处理者
 */
public class MyObserver implements Observer {

    /**
     * 观察者观察到目标变化时回调
     * @param o 目标对象
     * @param arg 目标对象产生的相关信息对象
     */
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("观察者观察到变化了:" + arg);
    }
}

public class TestObserver {

    public static void main(String[] args) {
        // 目标对象
        MyObservable observable = new MyObservable();
        // 观察者
        MyObserver observer = new MyObserver();
        // 绑定观察者和目标对象
        observable.addObserver(observer);
        // 目标对象产生变化
        observable.sendInfo("msg come");
    }
}

三、监听器和观察者的区别

这两者的相似之处就是当目标有变化自动回调函数的特点,这个特点也让他们在很多地方可以被对方替换。如果是自定义的事件,那么监听器和观察者都能解决问题,但是监听器看似更加原始和简单,如果都能完成功能,我们会倾向于监听器模式,如果要使用系统预设事件,比如鼠标点击,那么观察者就无能为力了,只能使用监听器。另外他们两者都是在业务编程过程中总结出来的模式,当项目代码繁杂量大时,使用模式会让人一目了然,如果使用简单的函数调用,会使逻辑不够清晰,这就是模式的作用,在小规模代码程序中,模式体现不了他的威力,这也是很多人难以掌握模式的原因:很多人难以接触大规模量项目。

你可能感兴趣的:(Java)