在MyBatis的兩萬多行的框架源碼中,使用了大量的設計模式對工程架構中的復雜場景進行解耦,這些設計模式的巧妙使用是整個框架的精華。
經過整理,大概有以下設計模式,如圖1所示。
型別:建立型模式
▊ 工廠模式
SqlSessionFactory 的結構如圖2所示。
工廠模式: 簡單工廠是一種建立型模式,在父類中提供一個建立物件的方法,允許子類別決定例項物件的型別。
場景介紹: SqlSessionFactory 是獲取會話的工廠,每次使用MyBatis 操作資料庫時, 都會開啟一個新的會話。在會話工廠的實作中,SqlSessionFactory 負責獲取資料來源環境配置資訊、構建事務工廠和建立操作SQL 的執行器,最終返回會話實作類。
同類設計: SqlSessionFactory、ObjectFactory、MapperProxyFactory 和DataSourceFactory。
▊ 單例模式
Configuration 單例配置類的結構如圖3所示。
單例模式: 是一種建立型模式,能夠保證一個類只有一個例項,並且提供一個存取該例項的全域節點。
場景介紹: Configuration 是一個大單例,貫穿整個會話周期,所有的配置物件(如對映、緩存、入參、出參、攔截器、序號產生器和物件工廠等)都在Configuration 配置項中初始化, 並且隨著SqlSessionFactoryBuilder 構建階段完成例項化操作。
同類場景: ErrorContext、LogFactory 和Configuration。
▊ 建造者模式
ResultMap 建造者模式的結構如圖4所示。
建造者模式: 使用多個簡單的物件一步一步地構建成一個復雜的物件,提供了一種建立物件的最佳方式。
場景介紹: 建造者模式在MyBatis 中使用了大量的XxxxBuilder,將XML 檔解析到各類物件的封裝中,使用建造者及建造者助手完成物件的封裝。它的核心目的是不希望把過多的關於物件的內容設定寫到其他業務流程中,而是用建造者方式提供最佳的邊界隔離。
同類場景: SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XML StatementBuilder 和CacheBuilder。
型別:結構型模式
▊ 介面卡模式
日誌實作類的結構如圖5所示。
介面卡模式: 是一種結構型模式,能使介面不相容的物件也可以相互合作。
場景介紹: 正是因為有太多的日誌框架,包括Log4j、Log4j2 和Slf4J 等,而這些日誌框架的使用介面又各有差異,為了統一這些日誌框架的介面,MyBatis 定義了一套統一的介面,為所有的其他日誌框架的介面做相應的適配。
同類場景: 主要集中在對Log 日誌的適配上。
▊ 代理模式
代理模式的實作結構如圖6所示。
代理模式: 是一種結構型模式,能夠提供物件的替代品或占位符。代理控制元物件的存取,並且允許在將請求送出給物件前進行一些處理。
場景介紹: 沒有代理模式就不存在各類框架。就像MyBatis 中的MapperProxy 實作類, 代理工廠實作的功能就是完成DAO 介面的具體實作類的方法,配置的任何一個DAO 介面呼叫的CRUD 方法,都會被MapperProxy 接管,呼叫到方法執行器等,並返回最終的資料庫執行結果。
同類場景: DriverProxy、Plugin、Invoker 和MapperProxy。
▊ 組合模式
解析節點類的結構如圖7所示。
組合模式: 是一種結構型模式,可以將物件組合成樹形結構以表示「部份—整體」 的階層。
場景介紹: 在MyBatis XML 動態的SQL 配置中,共提供了9 種標簽(trim、where、set、foreach、if、choose、when、otherwise 和bind),使用者可以組合出各類場景的SQL 語句。而SqlNode 介面的實作就是每個組合結構中的規則節點,透過規則節點的組裝,完成規則樹組合模式的使用。
同類場景: 主要體現在對各類SQL 標簽的解析上,以實作SqlNode 介面的各個子類別為主。
▊ 裝飾器模式
二級緩存裝飾器的實作結構如圖8所示。
裝飾器模式: 是一種結構型設計模式,允許將物件放入包含行為的特殊封裝物件中, 為元物件繫結新的行為。
場景介紹: MyBatis 的所有SQL 操作都是經過SqlSession 呼叫SimpleExecutor 完成的, 而一級緩存的操作也是在簡單執行器中處理的。這裏的二級緩存因為是基於一級緩存重新整理的,所以在實作上,透過建立一個緩存執行器,包裝簡單執行器的處理邏輯,實作二級緩 存操作。這裏用到的就是裝飾器模式,也叫俄羅斯套娃模式。
型別:行為型模式
▊ 樣版模式
SQL 執行樣版模式如圖9所示。
樣版模式: 是一種行為型模式,在超類中定義了一個演算法的框架,允許子類別在不修改結構的情況下重寫演算法的特定步驟。場景介紹:存在一系列可被標準定義的流程,並且流程的步驟大部份采用通用邏輯,只有一小部份是需要子類別實作的,通常采用樣版模式來定義這個標準的流程。就像MyBatis 的BaseExecutor 就是一個用於定義樣版模式的抽象類,在這個類中把查詢、修改的操作都定義為一套標準的流程。
同類場景: BaseExecutor、SimpleExecutor 和BaseTypeHandler。
▊ 策略模式
多型別處理器策略模式的結構如圖10所示。
策略模式: 是一種行為型模式,能定義一系列演算法,並將每種演算法分別放入獨立的類中,從而使演算法的物件能夠互相替換。
場景介紹: 在MyBatis 處理JDBC 執行後返回的結果時,需要按照不同的型別獲取對應的值,這樣就可以避免大量的if 判斷。所以,這瑞奇於TypeHandler 介面對每個參數型別分別做了自己的策略實作。
同類場景: PooledDataSource、UnpooledDataSource、BatchExecutor、ResuseExecutor、SimpleExector、CachingExecutor、LongTypeHandler、StringTypeHandler 和DateTypeHandler。
▊ 叠代器模式
拆解欄位解析實作的結構如圖11所示。
叠代器模式: 是一種行為型模式,能在不暴露集合底層表現形式的情況下遍歷集合中的所有元素。
場景介紹: PropertyTokenizer 用於MyBatis 的MetaObject 反射工具包下,用來解析物件關系的叠代操作。這個類在MyBatis 中使用得非常頻繁,包括解析資料來源配置資訊並填充到資料來源類上,同時參數的解析、物件的設定都會使用這個類。
同類場景: PropertyTokenizer。
總結
透過梳理,MyBatis大約運用了10種左右設計模式。可以說,復雜且優秀的ORM 框架源碼在設計和實作的過程中都會使用大量的設計模式。
在解決復雜場景的問題時,需要采用分治、抽象的方法,運用設計模式和設計原則等相關知識,把問題合理切割為若幹子問題,以便加以理解和解決。
學習源碼遠不是只是為了應付面試,更重要的是學習優秀框架在復雜場景下的解決方案。透過學習這些優秀的方案技術,可以提高對技術設計和實作的理解,擴充套件編碼思維,積累落地經驗。只有經過這樣長期的積累,我們才更有可能成為優秀的高級工程師和架構師。
本文節選自【手寫MyBatis:漸進式源碼實踐】一書,歡迎閱讀本書了解更多相關內容!
- END -
如喜歡本文,請點選右上角,把文章分享到朋友圈
如有想了解學習的技術點,請留言給若飛安排分享
因公眾號更改推播規則,請點「在看」並加「星標」 第一時間獲取精彩技術分享
·END·
相關閱讀:
來源: 網路
版權申明:內容來源網路,僅供學習研究,版權歸原創者所有。如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝!
架構師
我們都是架構師!
關註 架構師(JiaGouX),添加「星標」
獲取每天技術幹貨,一起成為牛逼架構師
技術群請 加若飛: 1321113940 進架構師群
投稿、合作、版權等信箱: [email protected]