观察者模式(Observer):一种行为型的设计模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

在Spring中,观察者模式常用的地方是Listener的实现,如ApplicationListener。

它一般由两个角色组成:发布者和订阅者(观察者)。观察者通常有一个回调,当然也可以没有。

在实际的工作中,监听器,日志收集,短信通知,邮件通知这些业务逻辑中可以考虑用到观察者模式。

下面以监听器来举例,在前端开发中,不管是js里面的click()时间,还是移动端app开发中的各种监听事件的捕获,都有用到观察者模式。

先来一个比较容易理解的实际例子。鼠标(Mouse)时间的监听,鼠标操作有单击(Click),双击(DoubleClick),移动(Move),悬停(Over),滚动(Wheel),弹起(Up),按下(Down)。

类图:

Java实现委托观察者模式 java观察者模式的实现_Spring

 Event类定义了事件的机制:

package Observer.core;

import java.lang.reflect.Method;

public class Event {
    //事件源
    private Object source;
    //通知目标
    private Object target;
    //回调方法
    private Method callback;
    //触发
    private String trigger;

    private Long time;

    public Event(Object target, Method callback) {
        this.target = target;
        this.callback = callback;
    }

    public Object getSource() {
        return source;
    }

    Event setSource(Object source) {
        this.source = source;
        return this;
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public Method getCallback() {
        return callback;
    }

    public void setCallback(Method callback) {
        this.callback = callback;
    }

    public String getTrigger() {
        return trigger;
    }

    Event setTrigger(String trigger) {
        this.trigger = trigger;
        return this;
    }

    public Long getTime() {
        return time;
    }

    Event setTime(Long time) {
        this.time = time;
        return this;
    }

    @Override
    public String toString() {
        return "Event{" +
                "\n\tsource=" + source + ",\n" +
                "\ttarget=" + target + ",\n" +
                "\tcallback=" + callback + ",\n" +
                "\ttrigger='" + trigger + '\'' + "\n" +
                '}';
    }


}

 EventListener类,是事件的注册和监听类,有一个Map相当于注册器,目的是存放各种触发的事件和相对应的条件。一般在观察者模式中都需要一个注册器。

package Observer.core;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 事件的注册和监听
 */
public class EventListener {
    //注册器
    protected Map<Enum,Event> events = new HashMap<Enum,Event>();

    public void addListener(Enum eventType, Object target, Method callback){
        //注册事件
        //用反射调用这个方法
        events.put(eventType,new Event(target,callback));
    }

    private void trigger(Event e){
        e.setSource(this);
        e.setTime(System.currentTimeMillis());

        try {
            e.getCallback().invoke(e.getTarget(),e); //使用反射的方法
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    //当注册器中查到相对应的时间,那么触发回调
    protected void trigger(Enum call){
        if(!this.events.containsKey(call)){ return ;}
        trigger(this.events.get(call).setTrigger(call.toString()));
    }


}

Mouse类:被观察者,继承于Eventlistener,定义了鼠标各种操作时候的情况:

package Observer.mouse;

import Observer.core.EventListener;

/**
 * 被观察者
 */
public class Mouse extends EventListener {
    public void click(){
        System.out.println("鼠标单击");
        this.trigger(MouseEventType.ON_CLICK);
    }


    public void doubleClick(){
        System.out.println("鼠标双击");
        this.trigger(MouseEventType.ON_DOUBLE_CLICK);
    }

    public void up(){
        System.out.println("鼠标弹起");
        this.trigger(MouseEventType.ON_UP);
    }

    public void down(){
        System.out.println("鼠标按下");
        this.trigger(MouseEventType.ON_DOWN);
    }


    public void wheel(){
        System.out.println("鼠标滚动");
        this.trigger(MouseEventType.ON_WHEEL);
    }

    public void move(){
        System.out.println("鼠标移动");
        this.trigger(MouseEventType.ON_MOVE);
    }

    public void over(){
        System.out.println("鼠标悬停");
        this.trigger(MouseEventType.ON_OVER);
    }
}

MouseEventType:枚举,里面存储mouse各种操作定义:

package Observer.mouse;

public enum MouseEventType {
    ON_CLICK,
    ON_DOUBLE_CLICK,
    ON_UP,
    ON_DOWN,
    ON_WHEEL,
    ON_MOVE,
    ON_OVER;
}

MouseEventCallback:观察者,回调响应的逻辑。

package Observer.mouse;

import Observer.core.Event;

/**
 * 回调响应的逻辑
 * 观察者
 */
public class MouseEventCallBack {
    public void onClick(Event e){
        System.out.println("这是鼠标单击以后要执行的逻辑");
        System.out.println("=======触发鼠标单击事件========\n" + e);
    }

    public void onDoubleClick(Event e){
        System.out.println("=======触发鼠标双击事件========\n" + e);
    }

    public void onUp(Event e){
        System.out.println("=======触发鼠标弹起事件========\n" + e);
    }
    public void onDown(Event e){
        System.out.println("=======触发鼠标按下事件========\n" + e);
    }
    public void onMove(Event e){
        System.out.println("=======触发鼠标移动事件========\n" + e);
    }
    public void onWheel(Event e){
        System.out.println("=======触发鼠标滚动事件========\n" + e);
    }

    public void onOver(Event e){
        System.out.println("=======触发鼠标悬停事件========\n" + e);
    }

}

测试类:

package Observer.mouse;

import Observer.core.Event;

import java.lang.reflect.Method;

public class MouseTest {
    public static void main(String[] args) {
        try {
            Mouse mouse = new Mouse();

            MouseEventCallBack mouseEventCallBack = new MouseEventCallBack();

            //方法定义
            Method onClick = MouseEventCallBack.class.getMethod("onClick", Event.class);
            Method onDoubleClick = MouseEventCallBack.class.getMethod("onDoubleClick", Event.class);
            Method onUp = MouseEventCallBack.class.getMethod("onUp", Event.class);
            Method onDown = MouseEventCallBack.class.getMethod("onDown", Event.class);
            Method onWheel = MouseEventCallBack.class.getMethod("onWheel", Event.class);
            Method onOver = MouseEventCallBack.class.getMethod("onOver", Event.class);
            Method onMove = MouseEventCallBack.class.getMethod("onMove", Event.class);

            //加入监听
            mouse.addListener(MouseEventType.ON_CLICK,mouseEventCallBack,onClick);
            mouse.addListener(MouseEventType.ON_DOUBLE_CLICK,mouseEventCallBack,onDoubleClick);
            mouse.addListener(MouseEventType.ON_UP,mouseEventCallBack,onUp);
            mouse.addListener(MouseEventType.ON_DOWN,mouseEventCallBack,onDown);
            mouse.addListener(MouseEventType.ON_WHEEL,mouseEventCallBack,onWheel);
            mouse.addListener(MouseEventType.ON_OVER,mouseEventCallBack,onOver);
            mouse.addListener(MouseEventType.ON_MOVE,mouseEventCallBack,onMove);

            //被观察者执行相对应的动作
            mouse.click();
            mouse.doubleClick();
            mouse.up();
            mouse.down();
            mouse.wheel();
            mouse.over();
            mouse.move();

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



    }
}

执行测试类输出结果:

Java实现委托观察者模式 java观察者模式的实现_Java实现委托观察者模式_02

可以看到,当对应的方法加入监听中之后,被观察者执行了什么操作,观察者也就有了对应的处理。