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中的具體實現。掌握組合模式可以幫助我們更好地設計和實現復雜結構的代碼,提高代碼的可維護性和擴展性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/45968.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45968.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45968.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【系統架構設計師】十二、系統質量屬性與架構評估(開發期質量屬性|運行期質量屬性|面向架構評估的質量屬性|質量屬性效用樹|質量屬性場景)

目錄 一、軟件系統質量屬性 1.1 開發期質量屬性 1.2 運行期質量屬性 1.3 面向架構評估的質量屬性 1.4 質量屬性效用樹 1.5 質量屬性場景 1.5.1 可用性質量屬性場景描述 1.5.2 可修改性質量屬性場景描述 1.5.3 性能質量屬性場景描述 相關推薦 歷年真題練習 歷…

【vue】輸入框和文本域切換

輸入框的樣子 文本域的樣子 當輸入框出現滾動條的時候&#xff0c;就自動切換成文本域&#xff1b;當文本域到1行并且寬度小于輸入框寬度時切換成輸入框 <div class"left_box_inpt"><divclass"right_box_inpt":class"{notclickable: inputd…

OpenResty使用Lua筆記

文章目錄 一、基礎1、常用2、使用局部變量3、模塊化 二、性能提升1、使用fft調用shell2、不要在循環中拼接字符串3、不要頻繁修改table4、不要在table中用nil5、做好異常處理6、ngx.var 的性能提升 三、拓展1、加載字符串為動態方法 一、基礎 1、常用 OpenResty 中文官網&…

Open3D 最小二乘法擬合點云平面

目錄 一、概述 1.1最小二乘法原理 1.2實現步驟 1.3應用場景 二、代碼實現 2.1關鍵函數 2.2完整代碼 三、實現效果 3.1原始點云 3.2matplotlib可視化 3.3平面擬合方程 前期試讀&#xff0c;后續會將博客加入該專欄&#xff0c;歡迎訂閱 Open3D點云算法與點云深度學習…

【學術會議征稿】第四屆人工智能、虛擬現實與可視化國際學術會議(AIVRV 2024)

第四屆人工智能、虛擬現實與可視化國際學術會議&#xff08;AIVRV 2024&#xff09; 2024 4th International Conference on Artificial Intelligence, Virtual Reality and Visualization 第四屆人工智能、虛擬現實與可視化國際學術會議&#xff08;AIVRV 2024&#xff09;將…

用python寫一個爬蟲,爬取google中關于蛇的照片

為了爬取Google中關于蛇的照片&#xff0c;我們可以利用Python中的第三方庫進行網頁解析和HTTP請求。請注意&#xff0c;這種爬取行為可能違反Google的使用條款&#xff0c;因此建議在合法和允許的情況下使用。以下是一個基本的Python爬蟲示例&#xff0c;使用Requests庫發送HT…

git 指令速查

1. 創建命令 Create Git 指令命令說明git clone 克隆遠程倉庫git init初始化本地 git 倉庫(即創建新的本地倉庫)2. 本地更改 Local Changes Git 指令命令說明git status查看當前分支狀態git diff查看已跟蹤文件的變更git add 將指定的文件添加到暫存區git add .將所有有變更的…

簡約唯美的404HTML源碼

源碼介紹 簡約唯美的404HTML源碼,很適合做網站錯誤頁,將下面的源碼放到一個空白的html里面,然后上傳到服務器里面即可使用 效果預覽 完整源碼 <!DOCTYPE html> <html><head><meta charset="utf-8"><title>404 Error Example<…

第二證券:市場估值依然處于較低區域 適合中長期布局

A股中報成績預告顯示相比2024Q1&#xff0c;2024Q2企業產品銷量或訂單已有回暖&#xff0c;但價格反轉暫未大面積到來&#xff0c;“量增價平、部分板塊以價換量”是2024H1 A股成績預告較顯著的量價特征&#xff0c;這與微觀庫存周期有待回暖相匹配。此外中游部分環節出現不同程…

Vue 3中使用 Lottie 動畫

一、Lottie動畫簡介 Lottie是由Airbnb開源的面向Android、iOS、Web和Windows的動畫庫,開發者可以使用它在Web、iOS、Android等平臺上實現高性能的體驗豐富的矢量動畫。 在早期的前端開發中,Flash是網頁動畫之王,不過它的規范約束隨意,造成很多時設計出來的產品都無法符合…

新版網頁無插件H.265播放器EasyPlayer.js如何測試demo視頻?

H5無插件流媒體播放器EasyPlayer屬于一款高效、精煉、穩定且免費的流媒體播放器&#xff0c;可支持多種流媒體協議播放&#xff0c;支持H.264與H.265編碼格式&#xff0c;性能穩定、播放流暢&#xff1b;支持WebSocket-FLV、HTTP-FLV&#xff0c;HLS&#xff08;m3u8&#xff0…

富格林:直面暗箱減少出金虧損

富格林悉知&#xff0c;在交易的過程中&#xff0c;投資者就算做好了十足的把握&#xff0c;也難免會出現出金虧損的情況。在這里建議新手投資者&#xff0c;在準備投資交易的時候&#xff0c;一定要做好充分的準備工作&#xff0c;了解黃金投資哪些暗箱陷阱&#xff0c;同時學…

【Linux】進程信號 --- 信號產生

&#x1f466;個人主頁&#xff1a;Weraphael ?&#x1f3fb;作者簡介&#xff1a;目前正在學習c和算法 ??專欄&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起進步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指點一二 如果文章對…

【轉型Web3開發第二課】Dapp開發入門基礎 | 02 | MetaMask配置網絡

本文首發于公眾號&#xff1a;Keegan小鋼 前言 完成了《轉型 Web3 開發第一課》之后&#xff0c;得到了不少讀者的認可&#xff0c;很多都在問什么時候開始下一課&#xff0c;近期終于抽出了時間開始搞起這第二課。 這第二課的主題為「Dapp開發入門基礎」&#xff0c;即想要轉…

淺談Visual Studio 2022

Visual Studio 2022&#xff08;VS2022&#xff09;提供了眾多強大的功能和改進&#xff0c;旨在提高開發者的效率和體驗。以下是一些關鍵功能的概述&#xff1a;12 64位支持&#xff1a;VS2022的64位版本不再受內存限制困擾&#xff0c;主devenv.exe進程不再局限于4GB&#xf…

【ffmpeg命令入門】重新編碼媒體流、設置碼率、設置幀速率

文章目錄 前言ffmpeg的描述重新編碼媒體流重新編碼媒體流的命令ffmpeg支持的媒體流 設置視頻碼率視頻碼率是什么設置視頻的碼率 設置文件幀數率幀數率是什么ffmpeg設置幀數率 總結 前言 在數字媒體處理領域&#xff0c;ffmpeg是一款非常強大的工具&#xff0c;它可以用來進行媒…

在線生成privacy-policy和 service-agreement

生成ppsa 網站 下面兩個是要收費的 局部功能可用 #1 Privacy Policy Generator - Privacy Policieshttps://termify.io/ 下面這個網站 創建一個是免費的 如果想要privacy-policy和 service-agreement 需要創建兩個賬戶 Termly

Java學習|JSON 處理庫:Gson、FastJson、Jackson的比較與使用指南

文章目錄 一、Gson簡介與使用注意事項1.1 簡介1.2 使用注意事項1.3 代碼示例序列化反序列化 二、FastJson簡介與使用注意事項2.1 簡介2.2 使用注意事項2.3 代碼示例序列化反序列化 三、Jackson簡介與使用注意事項3.1 簡介3.2 使用注意事項3.3 代碼示例序列化反序列化 四、關聯和…

svn不能記住密碼,反復彈出GNOME,自動重置svn.simple文件

1. 修改文件 打開 ~/.subversion/auth/svn.simple/xxx 更新前 K 15 svn:realmstring V 32 xxxxx //svn 地址&#xff0c;庫的地址 K 8 username V 4 xxx //用戶名 END在頂部插入下面內容&#xff0c; 注意&#xff0c;如果密碼不對&#xff0c;則文件文法正常生效 更新后…

37、PHP 實現一個鏈表中包含環,請找出該鏈表的環的入口結點

題目&#xff1a; 題目描述 PHP 實現一個鏈表中包含環&#xff0c;請找出該鏈表的環的入口結點。 描述&#xff1a; 一個鏈表中包含環&#xff0c;請找出該鏈表的環的入口結點。 <?php /*class ListNode{var $val;var $next NULL;function __construct($x){$this->v…