当前位置: 首页 > news >正文

使用TrieTree(字典树)来实现敏感词过滤

使用TrieTree(字典树)来实现敏感词过滤

1. 字典树定义

字典树(TrieTree),是一种树形结构,典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串,如01字典树)。主要思想是利用字符串的公共前缀来节约存储空间。很好地利用了串的公共前缀,节约了存储空间。字典树主要包含两种操作,插入和查找。
字典树具有以下规则:
-1. 根节点不包含字符,其他节点包含一个字符。

    1. 从根节点到某一节点经过的字符连接起来构成一个字符串。如图中的 him 、 her 、 cat 、 no 、 nova。
    1. 一个字符串与 Trie 树中的一条路径对应。
    1. 在实现过程中,会在叶节点中设置一个标志,用来表示该节点是否是一个字符串的结尾,本例中用isEnd标记。
      关于字典树的插入、删除等操作,可参考以下文章:

我来说说我对 Trie 数的理解。
下面是用Java实现的简易的TrieTree字典树

import java.util.HashMap;
import java.util.Map;public class TrieTree {public class TrieNode{public char value;public int isEnd; //0表示非终结 1表示终结public Map<Character,TrieNode>children;public TrieNode(char value,int isEnd){this.value=value;this.isEnd=isEnd;this.children=new HashMap<>();}public TrieNode(char value){this.value=value;this.isEnd=0;this.children=new HashMap<>();}public TrieNode(){this.isEnd=0;this.children=new HashMap<>();}}private TrieNode root;public TrieTree(){this.root=new TrieNode();}//插入敏感词汇public void insert(String str){if(str==null||str.length()==0){return ;}root=insert(root,str,0);}//判断字符串中,是否包含敏感词汇public boolean match(String str){if (str == null || "".equals(str)) {return false;}TrieNode temp=root;for(int i=0;i<str.length();i++){char ch=str.charAt(i);//获取到下一个节点TrieNode next = temp.children.get(ch);if (next==null){temp=root;}else{temp=next;}if (temp.isEnd==1){return true;}}return false;}//移除敏感词汇public void remove(String str){if (str == null || "".equals(str)) {return;}//没有该敏感词时,直接返回if (!match(str)){return;}//开始删除敏感词root=remove(root,str,0);}private TrieNode remove(TrieNode t,String str,int index){char ch=str.charAt(index);TrieNode child = t.children.get(ch);//到达最末尾if (index==str.length()-1){if (child.children.size()>0){//当前节点有子节点时,将标记为设置为0即可child.isEnd=0;}else{//否则直接删除该节点t.children.remove(ch);}return t;}//往下删除child=remove(child,str,++index);//回溯if (child.children.size()==0&&child.isEnd==1){//当没有节点并且isEnd==0时t.children.remove(ch);}return t;}private TrieNode insert(TrieNode t,String str,int index){char ch=str.charAt(index);TrieNode child = t.children.get(ch);if (child!=null){if (index==str.length()-1){child.isEnd=1;return t;}child=insert(child,str,++index);
//            t.children.put(ch,child);return t;}child=new TrieNode(ch);if (index==str.length()-1){child.isEnd=1;}else{child=insert(child,str,++index);}t.children.put(ch,child);return t;}public static void main(String[] args) {String[]sensitive={"华南理工","大学生","泰裤辣"};TrieTree trieTree=new TrieTree();for(int i=0;i<sensitive.length;i++){trieTree.insert(sensitive[i]);}System.out.println(trieTree.match("我是华南大学的学生"));System.out.println(trieTree.match("华北理工大学泰裤"));System.out.println(trieTree.match("华南理工大学"));System.out.println(trieTree.match("大学生"));System.out.println(trieTree.match("大学生泰裤辣"));System.out.println(trieTree.match("人之初性本善性相近习相远华南大学泰山崩于前而面不改色泰裤辣哈哈哈哈哈哈"));trieTree.remove("华南理工");System.out.println(trieTree.match("华南理工大学"));trieTree.remove("大学生");System.out.println(trieTree.match("大学生"));trieTree.remove("泰裤辣");System.out.println(trieTree.match("人之初性本善性相近习相远华南大学泰山崩于前而面不改色泰裤辣哈哈哈哈哈哈"));}
}

测试结果如下:
在这里插入图片描述

2. 使用字典树实现话题发布时,检查是否有敏感词汇

先创建三个表,分别是m_user用户表,m_topic话题表,m_sensitive敏感词汇表,表的具体内容如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
表的部分内容如下:
在这里插入图片描述
在这里插入图片描述
创建一个maven项目,添加下列依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.young</groupId><artifactId>trie01</artifactId><version>1.0-SNAPSHOT</version><parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version>2.7.0</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency></dependencies><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties></project>

application.yml

server:port: 8089
spring:datasource:username: rootpassword: 123456url: jdbc:mysql://localhost:3306/young?useSSL=false&serverTimezone=UTCdriver: com.mysql.cj.jdbc.Driver
mybatis-plus:global-config:db-config:logic-not-delete-value: 0logic-delete-value: 1

实体类信息如下图,其中User类中有一个字段isEnabled,我们可以使用这个字段,来约束用户的行为,但用户多次发布含有不当言论的话题时,将用户的isEnable置为0,这里为了方便演示,不实现该功能
在这里插入图片描述
相关的mapper
UserMapper.java

package com.young.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.young.entity.User;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserMapper extends BaseMapper<User> {
}

SensitiveMapper.java

package com.young.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.young.entity.Sensitive;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface SensitiveMapper extends BaseMapper<Sensitive> {
}

TopicMapper.java

package com.young.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.young.entity.Topic;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface TopicMapper extends BaseMapper<Topic> {
}

UserService.java

package com.young.service;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.young.entity.User;
import com.young.mapper.UserMapper;
import com.young.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public User login(String username,String password){LambdaQueryWrapper<User>queryWrapper=new LambdaQueryWrapper<>();queryWrapper.eq(User::getUsername,username).eq(User::getPassword,password);User user = userMapper.selectOne(queryWrapper);return user;}
}

TopicService.java

package com.young.service;import com.young.entity.Topic;
import com.young.exception.BusinessException;
import com.young.mapper.TopicMapper;
import com.young.vo.TrieTree;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.annotation.Resource;@Service
public class TopicService {@Autowiredprivate TopicMapper topicMapper;@Resourceprivate TrieTree trieTree;public boolean saveTopic(Topic topic){//判断是否有敏感词汇if (trieTree.match(topic.getTitle())||trieTree.match(topic.getContent())) {throw new BusinessException("发布内容中存在不当词汇,请遵守相关法律法规,营造良好的网络环境!!!");}return topicMapper.insert(topic)>0;}
}

SensitiveService.java,用于获取数据库中的敏感词汇表

package com.young.service;import com.young.entity.Sensitive;
import com.young.mapper.SensitiveMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;@Service
public class SensitiveService {@Autowiredprivate SensitiveMapper sensitiveMapper;public List<Sensitive>getAllSensitive(){return sensitiveMapper.selectList(null);}public List<String>getAllSensitiveWord(){List<Sensitive> allSensitive = getAllSensitive();if (allSensitive!=null&&allSensitive.size()>0){return allSensitive.stream().map(sensitive -> sensitive.getWord()).collect(Collectors.toList());}return new ArrayList<>();}
}

TrieTreeConfig.java,创建TrieTree的相关bean,方便后续使用

package com.young.config;import com.young.service.SensitiveService;
import com.young.vo.TrieTree;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.List;@Configuration
public class TrieTreeConfig {@Autowiredprivate SensitiveService sensitiveService;@Beanpublic TrieTree constructTrieTree(){System.out.println("初始化字典树======================");List<String> words = sensitiveService.getAllSensitiveWord();TrieTree trieTree=new TrieTree();for (String word : words) {trieTree.insert(word);}return trieTree;}
}

BusinessException.java

package com.young.exception;public class BusinessException extends RuntimeException{private String msg;public BusinessException(String msg){super(msg);}
}

GlobalExceptionHandler.java

package com.young.exception;import com.young.util.ResultVOUtil;
import com.young.vo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {@ExceptionHandler(BusinessException.class)public ResultVO businessExceptionHandler(BusinessException e){log.error("businessException:{}",e);return ResultVOUtil.fail(400,e.getMessage());}@ExceptionHandler(Exception.class)public ResultVO exceptionHandler(Exception e){log.error("exception:{}",e);return ResultVOUtil.fail(400,e.getMessage());}
}

相关的vo
在这里插入图片描述
ResultVOUtil.java

package com.young.util;import com.young.vo.ResultVO;public class ResultVOUtil <T>{public static <T> ResultVO<T> success(){return new ResultVO<>(200,"操作成功");}public static <T> ResultVO<T> success(T data){return new ResultVO<>(200,"操作成功",data);}public static <T> ResultVO<T> fail(){return new ResultVO<>(400,"操作失败");}public static <T> ResultVO<T> fail(Integer code,String msg){return new ResultVO<>(code,msg);}
}

DemoController.java,这里为了方便演示,用了session保存用户信息

package com.young.controller;import com.young.entity.Topic;
import com.young.entity.User;
import com.young.service.TopicService;
import com.young.service.UserService;
import com.young.util.ResultVOUtil;
import com.young.vo.ResultVO;
import com.young.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;@RestController
@RequestMapping("/user")
public class DemoController {@Autowiredprivate UserService userService;@Autowiredprivate TopicService topicService;@PostMapping("/login")public ResultVO login(@RequestBody UserVO userVO, HttpServletRequest request){User user = userService.login(userVO.getUsername(), userVO.getPassword());if (user==null){return ResultVOUtil.fail(400,"用户名或密码错误");}request.getSession().setAttribute("user",user);return ResultVOUtil.success(user);}@PostMapping("/topic")public ResultVO addTopic(@RequestBody Topic topic,HttpServletRequest request){User user = (User)request.getSession().getAttribute("user");if (user==null){return ResultVOUtil.fail(400,"用户未登录");}topic.setUserId(user.getId());if (topicService.saveTopic(topic)){return ResultVOUtil.success();}return ResultVOUtil.fail(400,"发布话题失败");}
}

运行项目,登录用户
在这里插入图片描述
发布文章(包含敏感词汇)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关文章:

使用TrieTree(字典树)来实现敏感词过滤

使用TrieTree&#xff08;字典树&#xff09;来实现敏感词过滤 1. 字典树定义 字典树&#xff08;TrieTree&#xff09;&#xff0c;是一种树形结构&#xff0c;典型应用是用于统计&#xff0c;排序和保存大量的字符串&#xff08;但不仅限于字符串,如01字典树&#xff09;。…...

USB转串口芯片CH9101U

CH9101是一个USB总线的转接芯片&#xff0c;实现USB转异步串口。提供了常用的MODEM联络信号&#xff0c;用于为计算机扩展异步串口&#xff0c;或者将普通的串口设备或者MCU直接升级到USB总线。 特点 全速USB设备接口&#xff0c;兼容USB V2.0。内置固件&#xff0c;仿真标准串…...

Java语言介绍

Java是一种广泛使用的计算机编程语言&#xff0c;由Sun Microsystems公司于1995年推出。它是一个健壮的、面向对象的、跨平台的语言&#xff0c;被用于开发各种应用程序和系统&#xff0c;包括Web应用程序、移动应用程序、桌面应用程序、游戏以及企业级系统等。 Java具有许多优…...

终于把 vue-router 运行原理讲明白了(二)!!!

一、vue-router路由变化侦测 1.1 上一遍文章中&#xff0c;介绍了vue-router 的install 函数的内部实现&#xff0c;知道了能在this中访问$router 和视图更新的机制&#xff0c;文章链接终于把 vue-router 运行原理讲明白了&#xff08;一&#xff09;&#xff01;&#xff01…...

ChatGPT实现服务器体验沙箱

服务器体验沙箱 IT 人员在学习一门新技术时&#xff0c;第一个入门门槛通常都是"如何在本地安装并成功运行"。因此&#xff0c;很多技术的官网都会通过沙箱技术&#xff0c;提供在线试用的 playground 或者按步模拟的 tour。让爱好者先在线尝试效果是否满足预期&…...

【算法】刷题中的位运算

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法篇 &#x1f43e;人类做题的过程&#xff0c;其实是暴搜的过程&#x1f43e; 文章目录 1.位运算概述2.位运算符3.位运算应用3.1整数的奇偶性判断3.2有关 2 的幂的应用3.3lowbit(x)返回x的最后一位13.4二进制数中1的个数3.5求…...

9.Java中异常处理机制是什么

Java的异常处理通过五个关键字来实现&#xff0c;分别是捕获异常&#xff1a;try&#xff0c;catchsfinally&#xff1b;声明异常&#xff1a;throws&#xff1b;抛出异常&#xff1a;throw 一&#xff1a;try&#xff0c;catch捕获异常二&#xff1a;finally回收资源三&#x…...

GeoTools实战指南: 叠加GeoTIFF与Shapefile图层生成截图

GeoTools实战指南: 叠加GeoTIFF与Shapefile图层生成截图 介绍 本教程将介绍如何使用GeoTools库在Java中将栅格数据(GeoTIFF)与矢量数据(Shapefile)叠加显示,并将结果保存为PNG格式的图片文件。我们将解析和分析 RasterDataRenderer 类,并了解其中的每个方法和对象。 准…...

nginx配置sh脚本远程执行一键安装

背景 本地多机重复操作某些shell指令&#xff0c;分步执行&#xff0c;很耗费时间&#xff0c; 需要远程一键部署&#xff0c;傻瓜化运维&#xff0c;更为通用安装。 即参考docker通用安装 sudo curl https://get.docker.com | sh - # sudo python3 -m pip install docker-co…...

Excel表格成绩排名全攻略,让你事半功倍!

在学校或公司中&#xff0c;我们经常需要对成绩进行排名。如果手动计算排名&#xff0c;不仅费时费力&#xff0c;而且容易出错。幸运的是&#xff0c;Microsoft Excel提供了一个简单而快速的方法来计算和显示排名。 在学校或公司中&#xff0c;成绩排名是一项重要的任务。使用…...

Docker 持久化存储 Bind mounts

Docker 持久化存储 Bind mounts Bind mounts 的 -v 与 --mount 区别启动容器基于bind mount挂载到容器中的非空目录只读 bind mountcompose 中使用 bind mount 官方文档&#xff1a;https://docs.docker.com/storage/bind-mounts/ Bind mounts 的 -v 与 --mount 区别 如果使用…...

LVS +Keepalived 高可用群集部署

一、LVSKeepalived 高可用群集 在这个高度信息化的 IT 时代&#xff0c;企业的生产系统、业务运营、销售和支持&#xff0c;以及日常管理等环节越来越依赖于计算机信息和服务&#xff0c;对高可用&#xff08;HA&#xff09;技术的应用需求不断提高&#xff0c;以便提供持续的…...

Kafka调优

生产者 参数名称描述bootstrap.serverskafka集群的地址key.deserializerkey的反序列化类&#xff0c;写全类名value.deserializervalue的反序列化类&#xff0c;写全类名buffer.memoryRecordAccumulator缓冲区总大小&#xff0c;默认32mbatch.size缓冲区一批数据最大值&#x…...

Debezium系列之:详细介绍Debezium2.X版本导出Sqlserver数据库Debezium JMX指标的方法

Debezium系列之:详细介绍Debezium2.X版本导出Sqlserver数据库Debezium JMX指标的方法 一、需求背景二、相关技术文章三、安装jmx_prometheus_javaagent四、Debezium2.X版本Sqlserver数据库jmx指标格式五、导出Debezium2.X版本Sqlserver数据库jmx指标方法六、Debezium2.X版本各…...

基于PWM技术的三相光伏逆变器研究(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

〖Python网络爬虫实战㉑〗- 数据存储之JSON操作

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;目前专栏免费订阅&#xff0c;在转为付费专栏前订阅本专栏的&#xff0c;可以免费订阅付…...

不得不说的行为型模式-责任链模式

目录 责任链模式&#xff1a; 底层原理&#xff1a; 代码案例&#xff1a; 下面是面试中可能遇到的问题&#xff1a; 责任链模式&#xff1a; 责任链模式是一种行为型设计模式&#xff0c;它允许多个对象在一个请求序列中依次处理该请求&#xff0c;直到其中一个对象能够…...

基于dsp+fpga+AD+ENDAC的半导体运动台高速数据采集电路仿真设计(四)

整个调试验证与仿真分析分三个步骤&#xff1a;第一步是进行 PCB 检查及电气特性测试&#xff0c;主 要用来验证硬件设计是否正常工作&#xff1b;第二步进行各子模块功能测试&#xff0c;包括高速光纤串行 通信的稳定性与可靠性测试&#xff0c; A/D 及 D/A 转换特性测…...

快速搭建Electron+Vite3+Vue3+TypeScript5脚手架 (无需梯子,快速安装Electron)

一、介绍 &#x1f606; &#x1f601; &#x1f609; Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.js 到 二进制的 Electron 允许您保持一个 JavaScript 代码代码库并创建 在Windows上运行的跨平台应用 macOS和Linux——不需…...

语义分割学习笔记(二)转置卷积

目录 1.转置卷积Transposed Convolution概念 2.转置卷积操作步骤 3.转置卷积参数 4.实战案例 推荐课程&#xff1a;转置卷积&#xff08;transposed convolution&#xff09;_哔哩哔哩_bilibili 感谢霹雳吧啦Wz&#xff0c;真乃神人也。 1.转置卷积Transposed Convolutio…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权

摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题&#xff1a;安全。文章将详细阐述认证&#xff08;Authentication) 与授权&#xff08;Authorization的核心概念&#xff0c;对比传统 Session-Cookie 与现代 JWT&#xff08;JS…...

02.运算符

目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&&#xff1a;逻辑与 ||&#xff1a;逻辑或 &#xff01;&#xff1a;逻辑非 短路求值 位运算符 按位与&&#xff1a; 按位或 | 按位取反~ …...

工厂方法模式和抽象工厂方法模式的battle

1.案例直接上手 在这个案例里面&#xff0c;我们会实现这个普通的工厂方法&#xff0c;并且对比这个普通工厂方法和我们直接创建对象的差别在哪里&#xff0c;为什么需要一个工厂&#xff1a; 下面的这个是我们的这个案例里面涉及到的接口和对应的实现类&#xff1a; 两个发…...