看了这么多年西游记,你可知道孙悟空是如何召唤土地公公的吗?

小时候最开心的事莫过于躺在沙发上看《西游记》了。大闹天宫、三打白骨精、真假美猴王……一幕幕精彩的故事萦绕脑海,现在想来,回味无穷。

不知道你有没有注意到这个细节:每当孙悟空到了一个新的环境需要了解本地的”风土人情”时,都会挥舞一下金箍棒,将土地召唤出来。那么你可知道,土地公公接收孙悟空召唤的原理是什么吗?

我们可以先将其理解为” 事件通知机制“,即每当孙悟空将金箍棒敲在地上时,就相当于给土地发了一封 email 的通知,告诉他俺老孙来了,赶快出来接驾。当土地收到通知之后就会立即现身了。

大家都知道 Spring 已经为我们提供好了 事件监听、订阅的实现,接下来我们用代码来实现一下这个场景。

首先我们要定义一个事件,来记录下孙悟空敲地的动作。

@Getter
public class MonkeyKingEvent extends ApplicationEvent {

    private MonkeyKing monkeyKing;

    public MonkeyKingEvent(MonkeyKing monkeyKing) {
        super("monkeyKing");
        this.monkeyKing = monkeyKing;
    }

}

其中 MonkeyKing 是我们定义好的孙悟空的实体类

@Data
public class MonkeyKing {

    /**
     * 是否敲地,默认为否
     **/
    private boolean knockGround = false;

}

然后我们需要实现 ApplicationListener 来监听孙悟空敲地的动作。

@Component
public class MyGuardianListener implements ApplicationListener {

    @Override
    public void onApplicationEvent(MonkeyKingEvent event) {
        boolean knockGround = event.getMonkeyKing().isKnockGround();
        if(knockGround){
            MyGuardian.appear();
        }else{
            MyGuardian.seclusion();
        }
    }
}

最后我们来验证下整个流程。

@PostMapping
public void testEvent(@RequestParam boolean knockGround) {
    MonkeyKing monkeyKing = new MonkeyKing();
    monkeyKing.setKnockGround(knockGround);
    MonkeyKingEvent monkeyKingEvent = new MonkeyKingEvent(monkeyKing);
    //发布孙悟空敲地的动作事件
    applicationEventPublisher.publishEvent(monkeyKingEvent);
}

当我们调用 testEvent()方法传入 knockGroundtrue 时,打印

土地公公出现了

传入为 false时,打印

土地公公遁地了

这样我们就简单实现了”孙悟空召唤土地”的功能。你以为这样就结束了?从小老师就教导我们要”知其然,更要知其所以然”。

大家都说读源码更像是在喝咖啡,读不懂又苦又涩,读懂了浓郁醇香。为了不影响大家的好心情,这里我们就不研究它的源码了,我们直捣黄龙。

说是 事件通知机制也好, 事件监听-订阅的实现也罢,其实它内部的最终实现原理依赖的是观察者模式。看到这,先不要胆怯,不要觉得设计模式晦涩难懂、久攻不下。今天我就用通俗易懂的小故事来带你重新认识一下观察者模式。

故事是这样的,上边我们只说了孙悟空敲地的动作,但是你是否还记得孙悟空将金箍棒往天上一指,便换来雷公电母、龙王等为其施法布雨?闭上双眼,与虎力大仙比试的场景仍历历在目。

由此可见,不光土地能收到孙悟空的通知,连雷公电母和龙王也是可以接收到的。在这里,我们把孙悟空比作主题,也就是大家说的被观察者和 Subject的概念,把雷公电母和龙王以及土地比作观察者。

以下是我们的代码逻辑:

首先,我们定义一个主题的基础类,里边会记录所有订阅该主题的观察者列表,还包含了增加、删除以及通知观察者的方法。

public class Subject {

    //观察者列表
    private Vector vector = new Vector();

    /**
     * 增加观察者
     **/
    public void addObserver(Observer observer){
        vector.add(observer);
    }

    /**
     *  删除观察者
     **/
    public void deleteObserver(Observer observer){
        vector.remove(observer);
    }

    /**
     *  通知所有观察者
     **/
    public void notifyObserver(String goldenCudgel) {
        for(Observer observer : vector) {
             observer.update(goldenCudgel);
         }
    }

}

然后,我们定义一个观察者的接口,包含观察者收到通知之后的”动作”。

public interface Observer {
    void update(String goldenCudgel);
}

这时候我们再分别定义出”土地”、”雷公电母”、”龙王”的观察者实体类,实现具体的打雷下雨等动作。

“雷公电母”、”龙王”等实现与”土地”类似,故此处仅展示观察者”土地”。

@Component
public class MyGuardianObserver implements Observer {

    @Override
    public void update(String goldenCudgel) {
        if(upGoldenCudgel(goldenCudgel)) {
            System.out.println("土地公公出现了");
        }
    }

    public boolean upGoldenCudgel(String goldenCudgel){
        if(Objects.equals(goldenCudgel,"down")){
            return true;
        }
        return false;
    }

}

接着,我们就可以定义被观察者的具体实现类”孙悟空”了

public class MonkeyKingSubject extends Subject{

    /**
     * 金箍棒是举起来还是放下呢?哈哈,你猜猜。。。
     **/
    public void doGoldenCudgel(String goldenCudgel){
        notifyObserver(goldenCudgel);
    }

}

最后我们来做个测试看看他们能不能响应孙悟空的通知。

@PostMapping
public void observerTest(){
    MonkeyKingSubject subject = new MonkeyKingSubject();
    subject.addObserver(new ThunderGodObserver());
    subject.addObserver(new MyGuardianObserver());
    subject.addObserver(new DragonKingObserver());

    subject.doGoldenCudgel("up");
    System.out.println("我是分割线-----------------------------");
    subject.doGoldenCudgel("down");
}

结果展示

雷公电母发出电闪雷鸣
龙王前来下雨
我是分割线-----------------------------
土地公公出现了

故事的最后怎么能少的了总结呢?观察者模式与事件通知机制都是在一对多的关系中,当一个对象被修改时,则会自动通知依赖它的对象,两者之间相互独立,互相解耦,这样既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。

当然它的缺点也不容忽视:

文章的最后,照例奉上源码,后台回复 event 即可获取。以上就是今天的全部内容了,如果你有不同的意见或者更好的 idea,欢迎联系阿Q,添加阿Q可以加入技术交流群参与讨论呦!

Original: https://www.cnblogs.com/aqsaycode/p/15627881.html
Author: 阿Q说代码
Title: 看了这么多年西游记,你可知道孙悟空是如何召唤土地公公的吗?

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/685580/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Golang中常用的代码优化点

    Golang中常用的代码优化点 大家好,我是轩脉刃。 这篇想和大家聊一聊golang的常用代码写法。在golang中,如果大家不断在一线写代码,一定多多少少会有一些些代码的套路和经…

    技术杂谈 2023年6月1日
    0101
  • tolua杂记

    1 字符串调用luaFunc :DoString public class CallLuaFunction : MonoBehaviour { private string scr…

    技术杂谈 2023年5月31日
    071
  • 「免费开源」基于Vue和Quasar的前端SPA项目crudapi后台管理系统实战之数据库逆向(十二)

    基于Vue和Quasar的前端SPA项目实战之数据库逆向(十二) 回顾 通过之前文章基于Vue和Quasar的前端SPA项目实战之动态表单(五)的介绍,实现了动态表单功能。如果是全…

    技术杂谈 2023年7月24日
    079
  • 负载均衡在web系统中的应用

    在日常的架构设计与开发中,常用的负载均衡算法主要分为静态和动态两类。静态负载算法以固定的频率分配任务不考虑服务器的状态信息,如轮询法、随机法等;动态负载均衡算法以服务器的实时负载状…

    技术杂谈 2023年7月25日
    089
  • Hosts映射

    Hosts映射 思考:如何通过主机名能够找到(ping)某个linux系统? 前言 Hosts:是一个文本文件,用来记录IP和Hostname的映射关系 DNS:是互联网上作为域名…

    技术杂谈 2023年6月21日
    087
  • 日常踩坑_jpa的踩坑心得

    背景提要 使用jpa的出现了很多问题1、使用between做日期范围查询时报错2、使用@Query注解写原生sql时报错3、使用@where注解自动在sql后添加条件时查不出东西4…

    技术杂谈 2023年7月25日
    073
  • AotucCrawler 快速爬取图片

    AotucCrawler 快速爬取图片 今天介绍一款自动化爬取图片项目。 GitHub: https://github.com/YoongiKim/AutoCrawler Goog…

    技术杂谈 2023年5月31日
    0107
  • Ubuntu解决Github无法访问的问题

    技术背景 由于IP设置的问题,有时候会出现Github无法访问的问题,经过一番的资料检索之后,发现如下的方案可以成功解决在Ubuntu下无法正常访问Github的问题(有时候可以打…

    技术杂谈 2023年7月25日
    0113
  • @Aspect

    AOP是指在程序运行期间动态地将某段代码切入到指定位置并运行的编程方式。 AOP详解可参考:https://blog.csdn.net/javazejian/article/det…

    技术杂谈 2023年7月24日
    089
  • 如何使用MBP制作Win启动盘

    最近有一个需求,想给家人的一台笔记本安装一套win 10的操作系统,但是我手头上现在没有对应的启动U盘。由于工作原因,很多年没用win了,工作电脑也都是MBP,根本没有之前使用wi…

    技术杂谈 2023年5月31日
    081
  • swap(a,b)异或骚操作方法

    众所周知,平日里我们如果要交换两个变量的时候,通常都是 void swap(int a, int b) { int temp = a; a = b; b = temp; } 通过创…

    技术杂谈 2023年7月24日
    077
  • C#调用C++dll,传指针释放内存问题

    一、传入dll前,在C#中申请内存空间 c#里面的指针即 IntPtr 申请如下: 这种需要提前知道空间大小,否则无法确定空间大小,会导致dll内部处理时越界报错。 c#里面申请空…

    技术杂谈 2023年7月24日
    093
  • Spring Ioc源码分析系列–Bean实例化过程(一)

    Spring Ioc源码分析系列–Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列–Ioc容器注册BeanPostProcesso…

    技术杂谈 2023年7月25日
    080
  • Hive的基本知识与操作

    Hive的基本知识与操作 Hive的基本知识与操作 Hive的基本概念 为什么使用Hive? Hive的特点: Hive的优缺点: Hive应用场景 Hive架构 Client M…

    技术杂谈 2023年7月11日
    086
  • Vue 模板语法

    Vue.js使用基于HTML的模板语法,允许开发者声明式地将DOM绑定至地层Vue实例的数据. 所有Vue.js的模板都是合法的HTML,所以能被遵循规范的浏览器和HTML解析器解…

    技术杂谈 2023年7月11日
    058
  • 使用Apache POI导出echarts图表到Excel表格

    转自:https://blog.csdn.net/weixin_44009447/article/details/105794496 引言:在实际项目统计报表模块中,报表的内容不单…

    技术杂谈 2023年5月31日
    0113
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球