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

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

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

我们可以先将其理解为” 事件通知机制“,即每当孙悟空将金箍棒敲在地上时,就相当于给土地发了一封 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)

大家都在看

  • CWE4.8:2022年危害最大的25种软件安全问题

    摘要:我们来看下新版的《2022年危害最大的25种安全问题》在安全预防上会给了我们哪些安全提示。 1. CWE 4.8的变化 2022年过了一半了,继《CWE 4.7中的新视图 –…

    技术杂谈 2023年5月31日
    0109
  • Python之NMAP详解

    NMap,也就是Network Mapper,最早是Linux下的网络扫描和嗅探工具包。 nmap是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端。确定哪些服务运行在哪些…

    技术杂谈 2023年7月11日
    0102
  • Spark学习(3)SparkSQL

    什么事sparkSQL Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrame并且作为分布式SQL查询引擎的作用, 它是将Spark…

    技术杂谈 2023年7月24日
    074
  • XAMPP本地配置SSL

    假设XAMPP安装目录为:H:_xampp 1、配置 C:\Windows\System32\drivers\etc\hosts 2、下载证书,复制到 H:_xampp\apach…

    技术杂谈 2023年5月31日
    088
  • java se 高级基础

    接口 继承树 Collection接口 Map接口 Collection 接口 Collection接口:单列集合,用来存储一个一个的对象 List接口:extends Colle…

    技术杂谈 2023年6月21日
    067
  • 个人学习-STL:Set前置-tree

    参考资料: [1]程杰.大话数据结构[M]. [2][美]Robert Sedgewic,Jevin Wayne. 算法Algorithms[M].谢路云译 1.基本脉络: 树实际…

    技术杂谈 2023年6月21日
    0111
  • DAX :【翻译】自动存在(auto-exist)

    自动存在是 DAX 中内置的一项技术,其唯一的目标是避免无用计算,换句话说,它是 DAX 的过滤机制使用的一种优化技术,目的是减少计算值的工作量。 例如,假设有人构建了一份按大陆和…

    技术杂谈 2023年5月31日
    097
  • Spring的循环依赖

    本文简要介绍了循环依赖以及Spring解决循环依赖的过程 循环依赖是指对象之间的循环依赖,即2个或以上的对象互相持有对方,最终形成闭环。这里的对象特指单例对象。 对象之间的循环依赖…

    技术杂谈 2023年7月24日
    052
  • DAX:跟关系相关的函数

    在表格数据模型中,用户可以创建关系,并可以沿着关系的方向自动进行交叉过滤。但是在 计算列中,必须通过RELATED 和 RELATEDTABLE函数来检索相关联的表。当使用CALC…

    技术杂谈 2023年5月31日
    085
  • 【赵渝强老师】史上最详细的PostgreSQL体系架构介绍

    PostgreSQL是最像Oracle的开源数据库,我们可以拿Oracle来比较学习它的体系结构,比较容易理解。PostgreSQL的主要结构如下: 一、存储结构 PG数据存储结构…

    技术杂谈 2023年7月24日
    054
  • 很详细的FFT(快速傅里叶变换)概念与实现

    FFT 首先要说明一个误区,很多人认为FFT只是用来处理多项式乘的,其实FFT是用来实现多项式的系数表示法和点值表示法的快速转换的,所以FFT的用处远不止多项式乘。 FFT的前置知…

    技术杂谈 2023年6月21日
    072
  • protoc将proto文件生成GO代码

    protoc将proto文件生成GO代码 protoc将proto文件生成GO代码 在WINDOWS终端里面输入命令:protoc –gofast_out . unit…

    技术杂谈 2023年5月31日
    071
  • 在线互联网地图资源汇总(仅学习用)

    Original: https://www.cnblogs.com/rainbow70626/p/16514207.htmlAuthor: rainbow70626Title: 在…

    技术杂谈 2023年6月1日
    076
  • mysql(DQL)

    MYSQL(康老师-DQL ) 1:基本的SELECT语句 1.1:基本的SELECT语句的课后练习 2:运算符 2.1:运算符课后练习 3.1排序 3.2分页 4.多表查询 4….

    技术杂谈 2023年7月25日
    055
  • SpringCloud 学习总结

    SpringCloud 学习总结 学习回顾 1.Maven依赖管理 ​ 在微服务项目中,我们一般是先创建一个父项目模块对整个项目的依赖进行版本限定和依赖控制,子模块继承父模块后,不…

    技术杂谈 2023年6月21日
    091
  • 未来数据库需要关心的硬核创新

    分享嘉宾:刘冰冰 亚马逊云科技 编辑整理:张了了 聚水潭 出品平台:DataFunTalk 导读:数据库经过了几十年的发展,目前已经是一项非常成熟的技术,然而随着当今互联网的极速增…

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