观察者模式

       定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象 都得到通知并被自动更新。
        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();
        }
    }
}

 

技术选型 【后端】:Java 【框架】:springboot 【前端】:vue 【JDK版本】:JDK1.8 【服务器】:tomcat7+ 【数据库】:mysql 5.7+ 项目包含前后台完整源码。 项目都经过严格调试,确保可以运行! 具体项目介绍可查看博主文章或私聊获取 助力学习实践,提升编程技能,快来获取这份宝贵的资源吧! 在当今快速发展的信息技术领域,技术选型是决定一个项目成功与否的重要因素之一。基于以下的技术栈,我们为您带来了一份完善且经过实践验证的项目资源,让您在学习和提升编程技能的道路上事半功倍。以下是该项目的技术选型和其组件的详细介绍。 在后端技术方面,我们选择了Java作为编程语言。Java以其稳健性、跨平台性和丰富的库支持,在企业级应用中处于领导地位。项目采用了流行的Spring Boot框架,这个框架以简化Java企业级开发而闻名。Spring Boot提供了简洁的配置方式、内置的嵌入式服务器支持以及强大的生态系统,使开发者能够更高效地构建和部署应用。 前端技术方面,我们使用了Vue.js,这是一个用于构建用户界面的渐进式JavaScript框架。Vue以其易上手、灵活和性能出色而受到开发者的青睐,它的组件化开发思想也有助于提高代码的复用性和可维护性。 项目的编译和运行环境选择了JDK 1.8。尽管Java已经推出了更新的版本,但JDK 1.8依旧是一种成熟且稳定的选择,广泛应用于各类项目中,确保了兼容性和稳定性。 在服务器方面,本项目部署在Tomcat 7+之上。Tomcat是Apache软件基金会下的一个开源Servlet容器,也是应用最为广泛的Java Web服务器之一。其稳定性和可靠的性能表现为Java Web应用提供了坚实的支持。 数据库方面,我们采用了MySQL 5.7+。MySQL是一种高效、可靠且使用广泛的关系型数据库管理系统,5.7版本在性能和功能上都有显著的提升。 值得一提的是,该项目包含了前后台的完整源码,并经过严格调试,确保可以顺利运行。通过项目的学习和实践,您将能更好地掌握从后端到前端的完整开发流程,提升自己的编程技能。欢迎参考博主的详细文章或私信获取更多信息,利用这一宝贵资源来推进您的技术成长之路!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值