Java架构师升级之路之设计模式(观察者模式< Observer>)

574 篇文章 4 订阅

观察者模式应用场景:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变,所有依赖与他的对象都能得到通知并被自动更新。
Spring中Observer模式中常用的地方是Listener的实现,如:ApplicationListener
图示:
在这里插入图片描述
在这里插入图片描述
O

代码演示:

package com.gupaoedu.observer;

/**
 * ClassName:SubjectEventType
 * PackageName:com.gupaoedu.observer
 * Description:
 *
 * @date:2020/7/23 21:43
 * @author:robin
 */
public enum SubjectEventType {
    //定义四个事件
    ON_ADD,
    ON_REMOVE,
    ON_EDIT,
    ON_QUERY;
}

package com.gupaoedu.observer;

/**
 * ClassName:Observer
 * PackageName:com.gupaoedu.observer
 * Description:
 * 你每做一件事情,我都观察到你,我做些事情,比如打印日志
 *举例:比如老师观察学生,只要学生上课吃辣条,老师就通知家长。
 *
 *
 * 观察者
 * @date:2020/7/23 20:33
 * @author:robin
 */
public class Observer {
    /**
     * 通知方法
     * @param e
     */
    public  void  advice(Event e){
        System.out.println("============触发事件,打印日志========="+"\n"+e);
    }
    /**
     * input.addListener("click",function(){
     *
     * })
     *
     *
     */
}

package com.gupaoedu.observer;

import java.lang.reflect.Method;

/**
 * ClassName:Event
 * PackageName:com.gupaoedu.observer
 * Description:
 *事件类
 * @date:2020/7/23 20:38
 * @author:robin
 */
public class Event {
    //事件源
    private  Object source;
    //通知目标类
    private  Object target;
    //回调
    private Method callback;
    //事件生成时间
    private  long time;
    //触发
    private String trigger;


    public Object getSource() {
        return source;
    }

     void setSource(Object source) {
        this.source = source;
    }

    public Object getTarget() {
        return target;
    }

    Event  setTarget(Object target) {
        this.target = target;
        //链式编程
        return  this;
    }

    public Method getCallback() {
        return callback;
    }

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

    public String getTrigger() {
        return trigger;
    }
    public long getTime() {
        return time;
    }
  //默认的访问权限,只能在同一个包下面使用
   Event setTime(long time) {
        this.time = time;
       //链式编程
        return this;
    }

    Event setTrigger(String trigger) {
        this.trigger = trigger;
        //链式编程
        return  this;
    }

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

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

package com.gupaoedu.observer;

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

/**
 * ClassName:EventListener
 * PackageName:com.gupaoedu.observer
 * Description:
 *注册器 类
 *
 * @date:2020/7/23 20:47
 * @author:robin
 */
public class EventListener {
    protected Map<Enum,Event> events=new HashMap<Enum, Event>();
    /**
     * input.addListener("click",function(){
     *
     * })
     * @param event
     * @param target
     * @param callback
     *
     * 注册事件的方法
     */
    public  void  addListener(Enum event, Object target, Method callback){
        //用反射调用这个对象
        events.put(event,new Event(target,callback));

    }

    /**
     * 触发事件的方法
     * @param e
     */
    private  void  trigger(Event e){
        e.setSource(this);
        e.setTime(System.currentTimeMillis());
        try{
            //调用观察者 advice(Event e)
            Method m = e.getCallback();
            m.invoke(e.getTarget(),e);
        }catch (Exception e1){
            e1.printStackTrace();
        }
    }

    /**
     * 触发事件
     * @param call
     */
    protected void trigger(Enum call){
        if (!this.events.containsKey(call)){return;}
        //触发内部的方法
        //this.events.get(call).setTrigger(call.toString()) 返回Event
        trigger(this.events.get(call).setTrigger(call.toString()));
    }
}

package com.gupaoedu.observer;

/**
 * ClassName:Subject
 * PackageName:com.gupaoedu.observer
 * Description:
 *被观察者
 * @date:2020/7/23 17:50
 * @author:robin
 * 让观察者与被观察者关联起来
 * 继承事件注册器
 */
public class Subject extends EventListener {
    //通常的话这里采用动态代理实现,避免了代码的侵入。
    public  void  add(){
        System.out.println("调用添加的方法");
           //触发方法(默认不执行,当被观察者注册事件subject.addListener()后才执行)
        trigger(SubjectEventType.ON_ADD);
    }
    public  void remove(){
        System.out.println("调用删除的方法");
        //触发方法
        trigger(SubjectEventType.ON_REMOVE);
    }
}

package com.gupaoedu.observer;

import java.lang.reflect.Method;

/**
 * ClassName:ObserverTest
 * PackageName:com.gupaoedu.observer
 * Description:
 *
 * @date:2020/7/23 21:46
 * @author:robin
 */
public class ObserverTest {
    public static void main(String[] args) {
        try{
            //创建一个观察者对象
            Observer observer=new Observer();
            Method advice= Observer.class.getMethod("advice",new Class<?>[]{Event.class});

           //这里写被观察对象
            Subject subject=new Subject();
            /**
             * public void addListener(Enum event,
             *                         Object target,
             *                         Method callback)
             */
         subject.addListener(SubjectEventType.ON_ADD,observer,advice);
         subject.add();  //注释掉了之后,上面监听方法(注册方法)不起效。
            //结论: 被观察者做事,观察者就做事。
            /**
             *
             * 输出结果
             *
             * 调用添加的方法
             * ============触发事件,打印日志=========
             * Event{source=com.gupaoedu.observer.Subject@14ae5a5, target=com.gupaoedu.observer.Observer@7f31245a, callback=public void com.gupaoedu.observer.Observer.advice(com.gupaoedu.observer.Event), trigger='ON_ADD'}
             */

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值