观察者模式

       定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象 都得到通知并被自动更新。
        Spring 中 Observer 模式常用的地方是 Listener 的实现。如 ApplicationListener。

归类特点穷举
行为模式

一般由两个对象组成:发布者和订阅者(观察者)。

观察者通常有一个回调,也可以没有。

监听器、日志收集、邮件通知

Demo

      事件与事件监听器(core包)

/**
 * @description: 事件
 **/
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;
    }

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


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

    public long getTime() {
        return time;
    }

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

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

     Event setTrigger(String trigger) {
        this.trigger = trigger;
        return this;
    }
}
/**
 * @description:事件的注册和监听
 **/
public class EventListener {

    //Map相当于一个注册器
    protected Map<Enum,Event> events = new HashMap<>();

    public void addListenter(Enum eventType, Object target, Method callback){
        //注册事件,将监听事件放在events的map中
        //用反射调用这个方法
        events.put(eventType,new Event(target,callback)); //target 就是observer  method 就是advice 在传参数时就传进来了
    }

    private void trigger(Event e){
        e.setSource(this);
        e.setTime(System.currentTimeMillis());
        //通过反射调用
        try {
            Method callback = e.getCallback();
            callback.invoke(e.getTarget(),e);  //invoke(Object obj, Object...args) obj 表示哪个对象,args表示方法的参数  callback 表示是哪个方法,此处 callback表示的advice方法,e.getTarget表示的observer 即 advice方法所在的类,e 表示method的参数
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    //触发事件的源头
    protected void trigger(Enum call){
        if(!this.events.containsKey(call)){
            return;
        }
        //此处调用trigger方法,并把 trigger 的值设置进去
        trigger(this.events.get(call).setTrigger(call.toString()));
    }
}

Observer(观察者)与Subject(被观察者)  (subject 包)

/**
 * @description:观察者
 **/
public class Observer {
    public void  advice(Event e){
        System.out.println("=====触发事件,打印日志=====\n" + e );
    }

}
/**
 * @description:被观察者
 **/
public class Subject extends EventListener {

    //通常的话,采用动态代理来实现监控,避免了代码的侵入
    public void add(){
        System.out.println("调用添加的方法");
        trigger(SubjectEventType.ON_ADD);
    }

    public void remove(){
        System.out.println("调用删除方法");
        trigger(SubjectEventType.ON_REMOVE);
    }
}
/**
 * @description: 被观察者事件枚举
 **/
public enum SubjectEventType {
    ON_ADD,
    ON_REMOVE,
    ON_EDIT,
    ON_QUERY
}
/**
 * @description:观察者测试类
 **/
public class ObserverTest {
    public static void main(String[] args) {
        try {
            //观察者
            Observer observer = new Observer();

            //获取advice   getMethod 时就获取了方法名和参数列表
            Method advice = Observer.class.getMethod("advice", new Class<?>[]{Event.class});

            //被观察者
            Subject subject = new Subject();
            //注册监听事件
            subject.addListenter(SubjectEventType.ON_ADD,observer,advice);
            subject.addListenter(SubjectEventType.ON_EDIT,observer,advice);
            subject.addListenter(SubjectEventType.ON_QUERY,observer,advice);
            subject.addListenter(SubjectEventType.ON_REMOVE,observer,advice);

            //调用方法
            subject.add();

            subject.remove();

        }catch(Exception e){

        }
    }
}

使用观察者模式实现鼠标点击事件

/**
 * @description:被观察者
 **/
public class Mouse extends EventListener {

    public void click(){
        System.out.println("鼠标单击");
        this.trigger(MouseEventType.ON_CLICK);
        this.trigger(MouseEventType.ON_CLICK_2);
    }

    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);
    }
}
/**
 * @description:回调响应的逻辑,由自己实现, 观察者
 **/
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);
    }

}
/**
 * @description:第二个观察者
 **/
public class MouseEventCallBack2 {
    public void onClick(Event e){
        System.out.println("这是第二个观察者中鼠标单击以后要执行的逻辑");
        System.out.println("======触发了鼠标单击事件========\n" + e);
    }
}
/**
 * @description: 鼠标事件枚举类型
 **/
public enum MouseEventType {
    ON_CLICK,
    ON_CLICK_2,
    ON_DOUBLE_CLICK,
    ON_UP,
    ON_DOWN,
    ON_WHEEL,
    ON_MOVE,
    ON_OVER
}
public class MouseTest {
    /**
     * var input = document.getElementById("username");
     * addLisenter相当于注册了一个事件并且给了一个注册逻辑
     * input.addLisenter("click",function(){
     * alert("鼠标点击了这个文本框");
     * });
     */
    public static void main(String[] args) {

        // 观察者和被观察者之间没有必然的联系,注册的时候,才会产生联系。
        // 观察者模式 最重要的就是动态解耦

        //代码时完全可以写在Mouse里面的,但是当Mouse产生的时候,callBack 还没有呢。所以就不可能再Mouse里面写代码了
        //因为Mouse产生后,我们在里面改不了了。所以才把这两个类隔离出来,进行动态解耦。
        //mouse 在前callback 在后,mouse并不清楚callback 回调要实现什么要的逻辑

        try {
            //回调事件1
            MouseEventCallBack callBack = new MouseEventCallBack();
            //反射获取回调方法1
            Method onClick = MouseEventCallBack.class.getMethod("onClick", Event.class);
            //回调事件2
            MouseEventCallBack2 callBack2 = new MouseEventCallBack2();
            //反射获取回调事件2
            Method onClick2 = MouseEventCallBack2.class.getMethod("onClick", Event.class);
            
            //人为调用鼠标的单击事件
            Mouse mouse = new Mouse();
            //增加callback的回调事件
            mouse.addListenter(MouseEventType.ON_CLICK, callBack,onClick );
            //增加callback2的回调事件
            mouse.addListenter(MouseEventType.ON_CLICK_2,callBack2,onClick2);

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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值