当前位置: 首页 > 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&…...

新手福音:在快马平台用一句话描述,AI帮你生成专属技能展示网页代码

作为一个刚入门编程的新手&#xff0c;想要展示自己的技能却无从下手&#xff1f;最近我发现了一个超级友好的工具&#xff0c;完全是为我们这种小白量身定做的。只需要简单描述需求&#xff0c;就能自动生成一个完整的个人技能展示网页项目&#xff0c;而且所有代码都带着详细…...

JTAG接口原理、故障诊断与安全操作指南

1. JTAG接口基础解析作为一名从事FPGA开发多年的工程师&#xff0c;我经常需要与JTAG接口打交道。这个看似简单的四线接口&#xff0c;在实际工作中却经常给我们带来各种"惊喜"。今天我就结合自己踩过的坑&#xff0c;系统地讲讲JTAG那些事儿。JTAG(Joint Test Actio…...

实战踩坑:antv G6与vite集成时的兼容性难题与解决方案

1. 当antv G6遇上vite&#xff1a;开发环境与生产环境的"薛定谔式报错" 最近接手一个数据可视化项目&#xff0c;需要用到antv G6这个流程图工具库。开发阶段一切顺利&#xff0c;页面渲染流畅得像德芙巧克力。但当我用vite打包准备上线时&#xff0c;控制台突然抛出…...

如何高效使用SpiecEasi进行微生物网络分析:microeco的完整指南

如何高效使用SpiecEasi进行微生物网络分析&#xff1a;microeco的完整指南 【免费下载链接】microeco An R package for data analysis in microbial community ecology 项目地址: https://gitcode.com/gh_mirrors/mi/microeco 在微生物生态学研究中&#xff0c;构建可靠…...

告别ArcGIS依赖!用QGIS 3.28把SHP属性表一键导出Excel,附赠3个数据清洗小技巧

告别ArcGIS依赖&#xff01;用QGIS 3.28高效导出SHP属性表到Excel的完整指南 当你在处理地理空间数据时&#xff0c;是否曾因ArcGIS的复杂操作或高昂成本而感到困扰&#xff1f;QGIS作为一款开源GIS软件&#xff0c;不仅完全免费&#xff0c;还能轻松完成从基础到高级的空间数据…...

给 Claude Code 装上浏览器:Chrome 集成测试版详解

程序员们早就习惯了在终端里跟 AI 助手聊天、改代码、跑测试。但有一个场景始终有点绕——代码改完了&#xff0c;得切到浏览器里看看效果、查查报错、填填表单&#xff0c;然后再切回终端告诉 AI “好像还差点意思”。来回折腾几次&#xff0c;思路容易断。 Anthropic 最近放出…...

终极TensorFlow Rust数学运算指南:从基础算术到复杂函数完全掌握

终极TensorFlow Rust数学运算指南&#xff1a;从基础算术到复杂函数完全掌握 【免费下载链接】rust Rust language bindings for TensorFlow 项目地址: https://gitcode.com/gh_mirrors/rust/rust TensorFlow Rust为开发者提供了强大的数学运算能力&#xff0c;通过Rust…...

webpack-blocks生态全景:从官方块到第三方扩展的完整盘点

webpack-blocks生态全景&#xff1a;从官方块到第三方扩展的完整盘点 【免费下载链接】webpack-blocks &#x1f4e6; Configure webpack using functional feature blocks. 项目地址: https://gitcode.com/gh_mirrors/we/webpack-blocks webpack-blocks是一个革命性的w…...

# 大数据开发面试题库

大数据开发岗面试必备&#xff1a;SQL 高频题、Spark 性能调优、数仓建模实战、项目经验梳理&#xff0c;覆盖初中级到高级岗位 &#x1f4cc; 前言 为什么面试总被问倒&#xff1f; 为什么项目经验说不清楚&#xff1f; 为什么调优问题总是泛泛而谈&#xff1f; 根本原因&am…...

Jimeng AI Studio应用场景:独立艺术家数字创作工作流整合方案

Jimeng AI Studio应用场景&#xff1a;独立艺术家数字创作工作流整合方案 1. 引言&#xff1a;当艺术家遇见AI 想象一下&#xff0c;你是一位独立艺术家或设计师。灵感来了&#xff0c;你想立刻把它变成一幅画、一张海报&#xff0c;或者一个全新的视觉概念。但传统的数字创作…...