观察者模式实现原理

18 篇文章 0 订阅

前言

观察者模式定义了对象之间的一对多依赖,让多个观察者对象同时监听一个主题对象,当主题对象发生变化时,它的所有观察者都会收到通知并作出相应的动作。
观察者模式又叫发布订阅模式,需要观察者对被观察者发布的的动作进行订阅。

实现

主要类

在这里插入图片描述
我们新建的这几个类中,Event是事件类,用于包装触发事件的相关信息;MouseEventType接口中定义了各种事件类型;EventLisenter是监听器类,它是观察者的桥梁;Mouse是被观察者类,当它作出动作时,观察者就会反应并作出相应动作。MouseEventCallback是观察者类
接下来我们就来实现一下

创建Event和MouseEventType

Event:

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 Event setSource(Object source) {
        this.source = source;
        return this;
    }
    public Event setTime(long time) {
        this.time = time;
        return this;
    }
    public Object getSource() {
        return source;
    }
    public Event setTrigger(String trigger) {
        this.trigger = trigger;
        return this;
    }
    public long getTime() {
        return time;
    }
    public Object getTarget() {
        return target;
    }
    public Method getCallback() {
        return callback;
    }
    @Override
    public String toString() {
        return "Event{" +
                "source=" + source +
                ", target=" + target +
                ", callback=" + callback +
                ", trigger='" + trigger + '\'' +
                ", time=" + time +
                '}';
    }
 }

MouseEventType:

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

Event为事件类,里面属性包含source事件源、target事件通知目标、callback事件回调、trigger事件名称
MouseEventType用于定义各种事件名称;

创建监听器类EventLisenter

这个类时观察者的桥梁
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();
        }
    }
    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));
    }

    private String toUpperFirstCase(String str) {
        char[] chars = str.toCharArray();
        chars[0] -= 32;
        return String.valueOf(chars);
    }

这个类中,用于事件订阅,里面将相应的事件存放到Map中,然后trigger是用于触发,通过传递进来的事件名称触发相应的事件

创建被观察者

Mouse :

public class Mouse extends EventLisenter{
    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 move() {
        System.out.println("调用移动方法");
        this.trigger(MouseEventType.ON_MOVE);
    }
    public void wheel() {
        System.out.println("调用滚动方法");
        this.trigger(MouseEventType.ON_WHEEEL);
    }
    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);
    }
}

这个类继承EventLisenter类,其相应的方法被调用会触发trigger方法

定义观察者类

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

测试

Test

public class Test {
    public static void main(String[] args) {
        try{
            MouseEventCallback callback = new MouseEventCallback();
            Mouse mouse = new Mouse();
            mouse.addLisenter(MouseEventType.ON_CLICK,callback);
            mouse.click();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试中,我们可以看到,被观察者mouse 使用addLisenter添加了一个监听事件,当其触发对应的方方时,会引起观察者相应的动作
我们测试看看
在这里插入图片描述
总结来说,这个观察者模式中,被观察者有一个注册表,初始化时,我们进行订阅,将相应的事件存放到注册表中,一旦被观察者作出某个动作,就会从注册表中拿到相应的事件并执行

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值