观察者模式Observer Pattern

观察者模式定义了对象之间的一对多依赖,让多个观察者对象同时监听一个主体,当主体对象发生变化时,它的所有观察者都会收到通知。观察者模式也叫发布订阅模式,主要用于在关联行为之间建立一套触发机制的场景。

下面通过我们平时最常用的键盘鼠标相关的监听事件作为例子,来熟悉观察者模式。

一、首先创建Event类

public class Event {
//    事件源,事件是由谁发起的,保存起来
    private Object source;
//    事件触发,要通知谁
    private Object target;
//    事件名称,触发的什么事件
    private String trigger;
//    回调函数,事件触发,要做什么动作
    private Method callback;
//    事件触发的时间
    private long time;

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

    public Event(Object source) {
        this.source = source;
    }

    public Object getSource() {
        return source;
    }

    public Object getTarget() {
        return target;
    }

    public Method getCallback() {
        return callback;
    }

    public String getTrigger() {
        return trigger;
    }

    public long getTime() {
        return time;
    }

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

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

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

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

    @Override
    public String toString() {
        return "Event{" +
                "source=" + source +
                ", target=" + target +
                ", trigger='" + trigger + '\'' +
                ", callback=" + callback +
                ", time=" + time +
                '}';
    }
}

二、创建事件监听EventLisenter 类

public class EventLisenter {
    protected Map<String, Event> events = new HashMap<String, Event>();

    public void addLisenter(String eventType, Object target) {
        try {
            this.addLisenter(eventType,
                    target,
                    target.getClass().getMethod("on" + toUpperFirstCase(eventType),
                            Event.class));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 注册事件
     *
     * @param eventType
     * @param target
     * @param callback
     */
    public void addLisenter(String eventType, Object target, Method callback) {
        events.put(eventType, new Event(target, callback));
    }

    //    触发,只要有动作就会触发
    private void trigger(Event event) {
        event.setSource(this);
        event.setTime(System.currentTimeMillis());
        try {
            if (event.getCallback() != null) {
                event.getCallback().invoke(event.getTarget(), event);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //    事件名称触发
    protected void trigger(String trigger) {
        if (!this.events.containsKey(trigger)) {
            return;
        }
        trigger(this.events.get(trigger).setTrigger(trigger));
    }

    /**
     * 首字母大写
     *
     * @param str
     * @return
     */
    private String toUpperFirstCase(String str) {
        char[] chars = str.toCharArray();
        chars[0] -= 32;
        return String.valueOf(chars);
    }
}

三、创建鼠标事件类型接口 MouseEventType,定义一些行为

public interface MouseEventType {
    static String ON_CLICK = "click";
    static String ON_DOUBLE_CLICK = "doubleClick";
    static String ON_UP = "up";
    static String ON_DOWN = "down";
    static String ON_MOVE = "move";
    static String ON_WHEEL = "wheel";
    static String ON_OVER = "over";
    static String ON_BLUR = "blur";
    static String ON_FOCUS = "focus";
}

四、创建 Mouse 类

public class Mouse extends EventLisenter {
    public void click(){
        System.out.println("调用单击方法");
        this.trigger(MouseEventType.ON_CLICK);
    }

    public void doublrClick(){
        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 move(){
        System.out.println("调用移动方法");
        this.trigger(MouseEventType.ON_MOVE);
    }

    public void wheel(){
        System.out.println("调用滚动方法");
        this.trigger(MouseEventType.ON_WHEEL);
    }

    public void over(){
        System.out.println("调用悬停方法");
        this.trigger(MouseEventType.ON_OVER);
    }

    public void blur(){
        System.out.println("调用获焦方法");
        this.trigger(MouseEventType.ON_BLUR);
    }

    public void focus(){
        System.out.println("调用失焦方法");
        this.trigger(MouseEventType.ON_FOCUS);
    }
}

五、创建 MouseEventCallback

public class MouseEventCallback {

    public void onClick(Event e){
        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);
    }

    public void onBlur(Event e){
        System.out.println("======获取鼠标获焦事件======"+"\n"+e);
    }

    public void onFocus(Event e){
        System.out.println("======获取鼠标失焦事件======"+"\n"+e);
    }
}

六、测试代码如下

public class Test {

    public static void main(String[] args) {
        MouseEventCallback callback = new MouseEventCallback();
        // 注册行为
        Mouse mouse = new Mouse();
        mouse.addLisenter(MouseEventType.ON_CLICK,callback);
        mouse.addLisenter(MouseEventType.ON_DOUBLE_CLICK,callback);
        mouse.addLisenter(MouseEventType.ON_UP,callback);
        mouse.addLisenter(MouseEventType.ON_DOWN,callback);
        mouse.addLisenter(MouseEventType.ON_MOVE,callback);
        mouse.addLisenter(MouseEventType.ON_OVER,callback);
        mouse.addLisenter(MouseEventType.ON_WHEEL,callback);
        mouse.addLisenter(MouseEventType.ON_BLUR,callback);
        mouse.addLisenter(MouseEventType.ON_FOCUS,callback);

        // 鼠标事件
        mouse.click();
        mouse.focus();
        mouse.down();
    }
}

打印结果如下:

调用单击方法
======获取鼠标单击事件======
Event{source=com.xiang.observer.Mouse@511d50c0, target=com.xiang.observer.MouseEventCallback@60e53b93, trigger='click', callback=public void com.xiang.observer.MouseEventCallback.onClick(com.xiang.observer.Event), time=1568537813240}
调用失焦方法
======获取鼠标失焦事件======
Event{source=com.xiang.observer.Mouse@511d50c0, target=com.xiang.observer.MouseEventCallback@60e53b93, trigger='focus', callback=public void com.xiang.observer.MouseEventCallback.onFocus(com.xiang.observer.Event), time=1568537813242}
调用按下方法
======获取鼠标按下事件======
Event{source=com.xiang.observer.Mouse@511d50c0, target=com.xiang.observer.MouseEventCallback@60e53b93, trigger='down', callback=public void com.xiang.observer.MouseEventCallback.onDown(com.xiang.observer.Event), time=1568537813242}

Process finished with exit code 0

我们可以看到,首先是把所有的监听对象注册进来,也就是事先确定有哪些观察者。然后调用被观察者的相应的方法,如:mouse.click()  mouse.focus() 等。通过这些触发事件会调用事件监听中的trigger方法,通过反射来调用(通知)观察者中对应的函数,来实现发布订阅的功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值