组合模式源码解析(jdk+mybatis)
生活随笔
收集整理的這篇文章主要介紹了
组合模式源码解析(jdk+mybatis)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
我們先看一下java.awt.container這么一個(gè)類(lèi),public class Container extends Component 我們可以看到這個(gè)類(lèi)繼承Component,awt這個(gè)包下邊都是實(shí)現(xiàn)窗口菜單,屬于編寫(xiě)C/S結(jié)構(gòu)所使用的,我們可以通過(guò)行為方法進(jìn)行識(shí)別,它是將相同的抽象類(lèi)的類(lèi)型,或者接口的類(lèi)型,這種類(lèi)型的實(shí)例轉(zhuǎn)換為樹(shù)狀結(jié)構(gòu),他本身Container繼承了Component,我們?cè)倏匆幌?他的add方法,public Component add(Component comp) {addImpl(comp, null, -1);return comp;
}他的add方法增加了一個(gè)Component,和我們是一樣的,課程目錄里面增加了一個(gè)自己的父類(lèi),這個(gè)就是通過(guò)行為方法來(lái)識(shí)別,同理我們來(lái)看一下java.util.HashMap,HashMap大家都很熟悉,public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {他呢實(shí)現(xiàn)了Map接口,同時(shí)我們?cè)倏匆幌滤膒utAll方法,public void putAll(Map<? extends K, ? extends V> m) {putMapEntries(m, true);
}putAll這個(gè)方法里面放的參數(shù)呢,也是一個(gè)Map,這里也是組合模式的一個(gè)應(yīng)用,同理我們?cè)倏匆幌麓蠹曳浅J煜さ?java.util下的List,我們直接看實(shí)現(xiàn)ArrayList,public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable同理他也是實(shí)現(xiàn)了List接口,然后看一下addAll這個(gè)方法,public boolean addAll(Collection<? extends E> c) {Object[] a = c.toArray();int numNew = a.length;ensureCapacityInternal(size + numNew); // Increments modCountSystem.arraycopy(a, 0, elementData, size, numNew);size += numNew;return numNew != 0;
}addAll里面直接添加了一個(gè)Collection,和Collection是什么關(guān)系呢,他實(shí)現(xiàn)了List接口,我們進(jìn)來(lái)public interface List<E> extends Collection<E> List接口又繼承了Collection接口,所以ArrayList里面的addAll,這個(gè)方法也正是組合模式的一個(gè)應(yīng)用,那set也是同理,那JDK講完了,我們?cè)倏匆幌略贛ybatis當(dāng)中,有什么應(yīng)用呢,我們看一個(gè)類(lèi),叫sqlnode,通過(guò)這個(gè)名字,就可以看出來(lái),這個(gè)就代表一個(gè)SQL節(jié)點(diǎn),我們看一下,package org.apache.ibatis.scripting.xmltags;/*** @author Clinton Begin*/
public interface SqlNode {boolean apply(DynamicContext context);
}組合模式就是把多個(gè)對(duì)象,組合成一個(gè)對(duì)象,簡(jiǎn)化對(duì)多個(gè)對(duì)象的訪問(wèn),對(duì)于Mybatis的MYSQL,一條SQL可以被解析成多個(gè)SQLNODE對(duì)象,SqlNode對(duì)象,有什么實(shí)現(xiàn)呢,我們Ctrl + T看一下,這里面有很多,我們使用了很多Mybatis的SQL,無(wú)論是集合的遍歷,還是where語(yǔ)句的一個(gè)拼裝,其實(shí)使用的都是SqlNode的這么一個(gè)父類(lèi),只不過(guò)對(duì)于Mybatis而言,各種SQL都會(huì)解析成不同的SqlNode對(duì)象,他們都屬于同一個(gè)類(lèi)型的對(duì)象,都實(shí)現(xiàn)了SqlNode接口,所以他們都是SqlNode對(duì)象,多個(gè)SqlNode怎么結(jié)合到一塊呢,我們看一下MixedSqlNode,這個(gè)就是他們的核心,這個(gè)就相當(dāng)于我們coding實(shí)戰(zhàn)當(dāng)中的課程目錄,課程目錄里面有很多課程,和這個(gè)是同理,我們可以看到他實(shí)現(xiàn)了SqlNode這個(gè)接口public class MixedSqlNode implements SqlNode {private 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;}
}同時(shí)里面還包含了多個(gè)SqlNode,這個(gè)就是CourseCatalog是一模一樣的,CourseCatalog他繼承了抽象類(lèi)CatalogComponent,只不過(guò)我們使用的是抽象類(lèi),而Mybatis使用的是接口,然后里面的items,相當(dāng)于MixedSqlNode的contents,然后下邊的apply也是循環(huán)遍歷,然后挨個(gè)進(jìn)行apply,把上下文再傳進(jìn)來(lái),那這個(gè)apply和我們現(xiàn)在的print方法,是異曲同工的,通過(guò)這么一個(gè)類(lèi)比,相信這一塊一定會(huì)理解更深入的,那我們接著回來(lái),所以我們?cè)谑褂媒M合模式的時(shí)候,最關(guān)鍵的一點(diǎn)是什么呢,就是葉子對(duì)象,和組合對(duì)象,都要實(shí)現(xiàn)相同的接口,或者繼承相同的抽象類(lèi),他們之間是要有這種關(guān)系的,只有達(dá)到這樣的關(guān)系,組合模式才能將葉子節(jié)點(diǎn)對(duì)象,還有組合好的對(duì)象,這種節(jié)點(diǎn)進(jìn)行一致的處理,那我們?cè)賮?lái)看一下,其他的實(shí)現(xiàn)比如WhereSqlNode,public class WhereSqlNode extends TrimSqlNode {private static List<String> prefixList = Arrays.asList("AND ","OR ","AND\n", "OR\n", "AND\r", "OR\r", "AND\t","OR\t");public WhereSqlNode(Configuration configuration, SqlNode contents) {super(configuration, contents, "WHERE", prefixList, null, null);}}可以看到這里面有一些他的實(shí)現(xiàn),比如他的前綴list,包括AND,OR,還有帶\n的AND,OR,還有帶\r的,還有帶\t的,他的構(gòu)造器就調(diào)用父類(lèi)的構(gòu)造器,然后把這些條件傳進(jìn)來(lái),比如prefix直接寫(xiě)了一個(gè)"WHERE",父類(lèi)就是調(diào)用TrimSqlNode,我們點(diǎn)進(jìn)來(lái)public TrimSqlNode(Configuration configuration, SqlNode contents, String prefix, String prefixesToOverride, String suffix, String suffixesToOverride) {this(configuration, contents, prefix, parseOverrides(prefixesToOverride), suffix, parseOverrides(suffixesToOverride));}他直接調(diào)用了這個(gè)構(gòu)造器,這個(gè)構(gòu)造器又調(diào)用了this,我們進(jìn)來(lái)看一下protected TrimSqlNode(Configuration configuration, SqlNode contents, String prefix, List<String> prefixesToOverride, String suffix, List<String> suffixesToOverride) {this.contents = contents;this.prefix = prefix;this.prefixesToOverride = prefixesToOverride;this.suffix = suffix;this.suffixesToOverride = suffixesToOverride;this.configuration = configuration;}this就把這些值賦值上apply的時(shí)候進(jìn)行使用@Overridepublic boolean apply(DynamicContext context) {FilteredDynamicContext filteredDynamicContext = new FilteredDynamicContext(context);boolean result = contents.apply(filteredDynamicContext);filteredDynamicContext.applyAll();return result;}所以對(duì)于SqlNode這么一個(gè)接口,可以說(shuō)是開(kāi)源框架中對(duì)于組合模式描述非常清晰的一個(gè)開(kāi)源框架源碼,希望你們?nèi)绻袝r(shí)間,來(lái)看一下,SqlNode其他節(jié)點(diǎn)的具體實(shí)現(xiàn),那我們可以通過(guò)UML看源碼的,可以快速的對(duì)你關(guān)心的源碼結(jié)構(gòu)有所了解,我們可以右鍵點(diǎn)開(kāi)show implementation,show實(shí)現(xiàn),這里面都是實(shí)現(xiàn)這個(gè)接口的類(lèi),我們直接按Ctrl + T挨個(gè)選一下,平時(shí)呢我也是使用這種辦法,來(lái)學(xué)習(xí)一些源碼,現(xiàn)在這個(gè)類(lèi)比較多
這里剛好放滿(mǎn)一屏,局部放大,SetSqlNode繼承了TrimSqlNode,然后上面的都實(shí)現(xiàn)了SqlNode接口,然后我們打開(kāi)他們的關(guān)系可以看一下,有些類(lèi)是組合關(guān)系,有些類(lèi)并不是組合關(guān)系,那我們可以對(duì)這些有差異的類(lèi),還有這些字段屬性,方法名字,都打開(kāi)之后,我們來(lái)看一下,那現(xiàn)在字體非常非常小,我們可以通過(guò)這種方式,來(lái)對(duì)整個(gè)SqlNode的實(shí)現(xiàn)呢,一目了然,因?yàn)槲覀儗W(xué)習(xí)了UML,來(lái)看這些圖還是很方便的,這個(gè)也是一個(gè)非常好的辦法,來(lái)學(xué)習(xí)源碼,希望你們能夠?qū)W習(xí)這個(gè)技能,那組合模式在我們?nèi)粘i_(kāi)發(fā)工作中,一定要注意我們coding過(guò)程中,碰到的那幾個(gè)坑,還有剛才講到的要有統(tǒng)一的接口實(shí)現(xiàn),或者統(tǒng)一的抽象父類(lèi)
?
總結(jié)
以上是生活随笔為你收集整理的组合模式源码解析(jdk+mybatis)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 组合模式coding
- 下一篇: 桥接模式讲解