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

MyBatis源码中的设计模式2

组合模式的应用

组合模式介绍

组合模式(Composite Pattern) 的定义是:将对象组合成树形结构以表示整体和部分的层次结构。组合模式可以让用户统一对待单个对象和对象的组合。

比如:Windows操作系统中的目录结构,通过tree命令实现树形结构展示。

在这里插入图片描述

在上图中包含了文件夹和文件两类不同元素,其中在文件夹中可以包含文件,还可以继续包含子文件夹。子文件夹中可以放入文件,也可以放入子文件夹。 文件夹形成了一种容器结构(树形结构),递归结构。

在这里插入图片描述

尽管文件夹和文件是不同类型的对象,它们有一个共性,就是都可以被放入文件夹中。文件和文件夹可以被当做是同一种对象看待。

组合模式其实就是将一组对象(文件夹和文件)组织成树形结构,以表示一种“部分-整体”的层次结构(目录与子目录的嵌套结构)。组合模式让客户端可以统一处理单个对象(文件)和组合对象(文件夹)的逻辑(递归遍历)。

组合模式更像是一种数据结构和算法的抽象,数据可以表示成树这种数据结构,业务需求可以通过在树上的递归遍历算法来实现。

在这里插入图片描述

组合模式主要包含三种角色:

  • 抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。

    • 包含所有子类共有行为的声明和实现。在抽象根节点中定义了访问及管理子构件的方法,如增加子节点、删除子节点、获取子节点等。
  • 树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构。

    • 树枝节点可以包含树枝节点,也可以包含叶子节点。它其中有一个集合可以用于存储子节点,包含在抽象根节点中定义的行为。业务方法中可以递归调用其子节点的业务方法。
  • 叶子节点(Leaf):叶子节点对象,其下再无分支,是系统层次遍历的最小单位。

    • 叶子节点没有子节点,包含在抽象根节点中定义的行为。

组合模式示例

程序功能:列出某一目录下所有的文件和文件夹。

类图如下:

在这里插入图片描述

我们按照下图的表示,进行文件和文件夹的构建。

在这里插入图片描述

Entry类: 抽象类,用来定义File类和Directory类的共性内容

/*** Entry抽象类,表示目录条目(文件+文件夹)的抽象类*/
public abstract class Entry {public abstract String getName(); // 获取文件名public abstract int getSize(); // 获取文件大小// 添加文件夹或文件public abstract Entry add(Entry entry);// 显示指定目录下的所有信息public abstract void printList(String prefix);@Overridepublic String toString() {return getName() + "(" + getSize() + ")";}
}

File类: 叶子节点,表示文件

/*** File类 表示文件*/
public class File extends Entry {private String name; // 文件名private int size; // 文件大小public File(String name, int size) {this.name = name;this.size = size;}@Overridepublic String getName() {return name;}@Overridepublic int getSize() {return size;}@Overridepublic Entry add(Entry entry) {return null; // 叶子节点不能添加子节点}@Overridepublic void printList(String prefix) {System.out.println(prefix + "/" + this);}
}

Directory类: 树枝节点,表示文件夹

/*** Directory表示文件夹*/
public class Directory extends Entry {private String name; // 文件夹名private ArrayList<Entry> directory = new ArrayList<>(); // 文件夹与文件的集合public Directory(String name) {this.name = name;}@Overridepublic String getName() {return this.name;}/*** 获取文件大小* 1.如果entry对象是File类型,则调用getSize方法获取文件大小* 2.如果entry对象是Directory类型,会继续调用子文件夹的getSize方法,形成递归调用.*/@Overridepublic int getSize() {int size = 0;for (Entry entry : directory) {size += entry.getSize();}return size;}@Overridepublic Entry add(Entry entry) {directory.add(entry);return this;}@Overridepublic void printList(String prefix) {System.out.println(prefix + "/" + this);for (Entry entry : directory) {entry.printList(prefix + "/" + name);}}
}

测试代码

public class Client {public static void main(String[] args) {// 根节点Directory rootDir = new Directory("root");// 树枝节点Directory binDir = new Directory("bin");// 向bin目录中添加叶子节点binDir.add(new File("vi", 10000));binDir.add(new File("test", 20000));Directory tmpDir = new Directory("tmp");Directory usrDir = new Directory("usr");Directory mysqlDir = new Directory("mysql");mysqlDir.add(new File("my.cnf", 30));mysqlDir.add(new File("test.db", 25000));usrDir.add(mysqlDir);rootDir.add(binDir);rootDir.add(tmpDir);rootDir.add(mysqlDir);rootDir.printList("");}
}

组合模式优点

  1. 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。
  2. 在组合模式中增加新的树枝节点和叶子节点都很方便,无须对现有类库进行任何修改,符合“开闭原则”。
  3. 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子节点和树枝节点的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。

组合模式缺点

  • 使用组合模式的前提在于,你的业务场景必须能够表示成树形结构。所以,组合模式的应用场景也比较局限,它并不是一种很常用的设计模式。

组合模式使用场景分析

  • 处理一个树形结构,比如,公司人员组织架构、订单信息等;
  • 跨越多个层次结构聚合数据,比如,统计文件夹下文件总数;
  • 统一处理一个结构中的多个对象,比如,遍历文件夹下所有 XML 类型文件内容。

MyBatis中的应用

MyBatis支持动态SQL的强大功能,比如下面的这个SQL:

<update id="update" parameterType="org.format.dynamicproxy.mybatis.bean.User">UPDATE users<trim prefix="SET" prefixOverrides=","><if test="name != null and name != ''">name = #{name}</if><if test="age != null and age != ''">, age = #{age}</if><if test="birthday != null and birthday != ''">, birthday = #{birthday}</if></trim>where id = ${id}
</update>

在这里面使用到了trim、if等动态标签,我们可以根据实际的业务需求,动态地拼装SQL语句。这些动态SQL标签在MyBatis中被解析后会被转换为不同的SQL节点树结构,通过组合模式将这些SQL节点组织在一起,最后生成完整的SQL语句。

MyBatis中用组合模式的例子有MixedSqlNodeTrimSqlNodeChooseSqlNodeIfSqlNodeWhereSqlNode等。

我们通过查看MixedSqlNode类的源码,可以看到组合模式的应用。

public class MixedSqlNode implements SqlNode {private final List<SqlNode> contents;public MixedSqlNode(List<SqlNode> contents) {this.contents = contents;}@Overridepublic boolean apply(DynamicContext context) {for (SqlNode sqlNode : contents) {sqlNode.apply(context);}return true;}
}

MixedSqlNode类中,包含了一个List<SqlNode>集合contents,它可以包含SqlNode类型的对象,如IfSqlNodeTrimSqlNodeWhereSqlNode等。这些节点可以组成一个复杂的树形结构,通过递归调用它们的apply方法,可以逐步生成完整的SQL语句。

例如,IfSqlNode类的源码:

public class IfSqlNode implements SqlNode {private final ExpressionEvaluator evaluator;private final String test;private final SqlNode contents;public IfSqlNode(SqlNode contents, String test) {this.test = test;this.contents = contents;this.evaluator = new ExpressionEvaluator();}@Overridepublic boolean apply(DynamicContext context) {if (evaluator.evaluateBoolean(test, context.getBindings())) {contents.apply(context);return true;}return false;}
}

IfSqlNode中,它包含一个SqlNode类型的contents,表示如果条件满足时需要执行的SQL节点。通过调用contents.apply(context),可以将子节点的内容拼接到当前的SQL上下文中。

总结

组合模式在处理复杂结构时非常有用,尤其是树形结构和递归处理的场景。它可以通过统一接口处理单个对象和组合对象,简化了代码的实现和维护。在MyBatis中,组合模式被广泛应用于动态SQL的生成过程中,通过不同类型的SQL节点组织成树形结构,递归地生成最终的SQL语句。

通过以上内容,我们了解了组合模式的定义、结构、优缺点以及在实际中的应用,特别是在MyBatis中的具体实现。掌握组合模式可以帮助我们更好地设计和实现复杂结构的代码,提高代码的可维护性和扩展性。

相关文章:

MyBatis源码中的设计模式2

组合模式的应用 组合模式介绍 组合模式(Composite Pattern) 的定义是&#xff1a;将对象组合成树形结构以表示整体和部分的层次结构。组合模式可以让用户统一对待单个对象和对象的组合。 比如&#xff1a;Windows操作系统中的目录结构&#xff0c;通过tree命令实现树形结构展…...

AI发展中的伦理挑战与应对策略

AI发展中的伦理挑战与应对策略 人工智能&#xff08;AI&#xff09;的快速发展在为社会带来许多便利和创新的同时&#xff0c;也带来了诸多伦理挑战。这些挑战主要集中在数据隐私侵犯、信息茧房的制造、歧视性算法、深度伪造技术等方面。针对这些问题&#xff0c;需要从多个层…...

基于用户非兴趣/非偏好/非习惯的推荐

基于用户非兴趣、非偏好、非习惯的推荐是一种个性化推荐技术&#xff0c;旨在为用户提供与其日常行为和兴趣模式不同的推荐内容。这种推荐方法的目的是打破用户的信息过滤和习惯&#xff0c;发现新的、潜在的兴趣点&#xff0c;从而提供更广泛和多样化的推荐结果。 通过收集和分…...

Abaqus基于CT断层扫描的三维重建插件CT2Model 3D

插件介绍 AbyssFish CT2Model 3D V1.0 插件可将采用X射线等方法获取的计算机断层扫描&#xff08;CT&#xff09;图像在Abaqus有限元软件内进行三维重建&#xff0c;进而高效获取可供模拟分析的有限元模型。插件可用于医学影像三维重构、混凝土细观三维重建、岩心数字化等领域…...

Mindspore框架CycleGAN模型实现图像风格迁移|(三)损失函数计算

Mindspore框架&#xff1a;CycleGAN模型实现图像风格迁移算法 Mindspore框架CycleGAN模型实现图像风格迁移|&#xff08;一&#xff09;CycleGAN神经网络模型构建 Mindspore框架CycleGAN模型实现图像风格迁移|&#xff08;二&#xff09;实例数据集&#xff08;苹果2橘子&…...

ENSP中VLAN的设置

VLAN的详细介绍 VLAN&#xff08;Virtual Local Area Network&#xff09;即虚拟局域网&#xff0c;是一种将一个物理的局域网在逻辑上划分成多个广播域的技术。 以下是关于 VLAN 的一些详细介绍&#xff1a; 一、基本概念 1. 作用&#xff1a; - 隔离广播域&#xff1a…...

《后端程序员 · Nacos 常见配置 · 第一弹》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

深入解析HTTPS与HTTP

在当今数字化时代&#xff0c;网络安全已成为社会各界关注的焦点。随着互联网技术的飞速发展&#xff0c;个人和企业的数据安全问题日益凸显。在此背景下&#xff0c;HTTPS作为一种更加安全的通信协议&#xff0c;逐渐取代了传统的HTTP协议&#xff0c;成为保护网络安全的重要屏…...

vue3+TS从0到1手撸后台管理系统

1.路由配置 1.1路由组件的雏形 src\views\home\index.vue&#xff08;以home组件为例&#xff09; 1.2路由配置 1.2.1路由index文件 src\router\index.ts //通过vue-router插件实现模板路由配置 import { createRouter, createWebHashHistory } from vue-router import …...

黑马头条-环境搭建、SpringCloud

一、项目介绍 1. 项目背景介绍 项目概述 类似于今日头条&#xff0c;是一个新闻资讯类项目。 随着智能手机的普及&#xff0c;人们更加习惯于通过手机来看新闻。由于生活节奏的加快&#xff0c;很多人只能利用碎片时间来获取信息&#xff0c;因此&#xff0c;对于移动资讯客…...

基于centos2009搭建openstack-t版-ovs网络-脚本运行

openstackT版脚本 环境变量ip初始化 controlleriaas-pre.shiaas-install-mysql.shiaas-install-keystone.shiaas-install-glance.shiaas-install-placement.shiaas-install-nova-controller.shiaas-install-neutron-controller.shiaas-install-dashboard.sh computeiaas-instal…...

buuctf-web

查看后端源码 得到base64编码&#xff0c;解码得flag...

UBUNTU22 安装QT5.15.2 记录

安装QT预置安装软件包 sudo apt install gcc sudo apt install g sudo apt install clang sudo apt install clang sudo apt install make sudo snap install cmake --classic sudo apt-get install build-essential sudo apt install libxcb-xinerama0 #安装OpenGL核心库 su…...

C++基础知识:C++内存分区模型,全局变量和静态变量以及常量,常量区,字符串常量和其他常量,栈区,堆区,代码区和全局区

1.C内存分区模型 C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区:存放函数体的二进制代码&#xff0c;由操作系统进行管理的&#xff08;在编译器中所书写的代码都会存放在这个空间。&#xff09; 全局区:存放全局变量和静态变量以及常量 栈区:由编译器自动分…...

MySQL面试题-重难点

mysql中有哪些锁&#xff1f;举出所有例子&#xff0c;各个锁的作用是什么&#xff1f;区别是什么&#xff1f; 共享锁&#xff1a;也叫读锁&#xff0c;简称S锁&#xff0c;在事务要读取一条记录时&#xff0c;先获取该记录的S锁&#xff0c;别的事务也可以继续获取该记录的S…...

【Linux杂货铺】期末总结篇3:用户账户管理命令 | 组账户管理命令

&#x1f308;个人主页&#xff1a;聆风吟_ &#x1f525;系列专栏&#xff1a;Linux杂货铺、Linux实践室 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 第五章5.1 ⛳️Linux 账户5.2 ⛳️用户配置文件和目录&#xff08;未完待续&#xff09;5.2.1 …...

基于STM32设计的超声波测距仪(微信小程序)(186)

基于STM32设计的超声波测距仪(微信小程序)(186) 文章目录 一、前言1.1 项目介绍【1】项目功能介绍【2】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】ESP8266工作模式配置1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献1.4 开发工具的选择1.5 系统框架图…...

Web前端-Web开发HTML基础2-list

一. 基础 1. 写一个列表标签&#xff0c;生成一个有三条记录的无序列表&#xff1b; 2. 写一个列表标签&#xff0c;生成一个有四条记录的无序列表&#xff1b; 3. 写一个列表标签&#xff0c;生成一个有五条记录的无序列表&#xff1b; 4. 写一个列表标签&#xff0c;生成一个…...

MAVSDK-Java安卓客户端编译与使用完整示例

效果&#xff1a; 1.启动PX4容器 2.监听QGC连接端口 3.手机与QGC连接到同一局域网&#xff08;此例QGC为&#xff1a;192.168.6.250 手机为&#xff1a;192.168.6.86&#xff09; 4.监听手机mavsdk_server连接端口 5.使用Android Studio打开MAVSDK-JAVA下的examples/android-c…...

JavaEE:Spring Web简单小项目实践二(用户登录实现)

学习目的&#xff1a; 1、理解前后端交互过程 2、学习接口传参&#xff0c;数据返回以及页面展示 1、准备工作 创建SpringBoot项目&#xff0c;引入Spring Web依赖&#xff0c;添加前端页面到项目中。 前端代码&#xff1a; login.html <!DOCTYPE html> <html lang&…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

鸿蒙HarmonyOS 5军旗小游戏实现指南

1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;采用DevEco Studio实现&#xff0c;包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天&#xff0c;今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案&#xff0c;它们不仅提供了优雅的设计思路&#xff0c;还能显著提升系统的性能…...

医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor

1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...