大戰設計模式(第二季)【1】———— 從原始碼看工廠模式
前言
工廠模式其實在許多地方都有體現,是常見的一種設計模式。用一句話總結就是,當我們需要建立一些物件的時候,而建立的物件比較複雜或者同類型比較多,就可以使用它。
在我們看原始碼的時候,有的時候看見XXXFactory那麼它就使用了工廠模式。
工廠模式的基礎知識點:
簡單工廠: https://www.cnblogs.com/linkstar/p/7657865.html
工廠方法: https://www.cnblogs.com/linkstar/p/7667799.html
抽象工廠: https://www.cnblogs.com/linkstar/p/7672733.html
全部設計模式: https://www.cnblogs.com/linkstar/category/1087887.html
Calendar來看簡單工廠
首先我們常見的jdk中有一個叫做Calendar的類,它是專門用來處理時間的,它是一個抽象類,我們只能使用getInstance方法獲取這個類的例項。


然後然後其中會通過createCalendar方法去建立這個物件。因為各個國家的日曆可能都有所不同,所以需要根據地區來返回對應的實現,比如日本的話就會返回JapaneseImperialCalendar物件。


這裡其實就是簡單工廠的一個體現,根據具體傳入的引數不同,返回的不同實現的產品。
從Collection看工廠方法
在jdk中Collection介面中有一個iterator方法,這個方法是返回一個迭代器物件,這個物件是用來遍歷集合的,我們在一開始學習java的時候就經常使用迭代器來遍歷集合。
這其實就是一個工廠方法,而這個方法的具體實現的各個工廠就有很多了,比如ArrayList,HashSet等,他們都是工廠,而抽象的產品是Iterator介面。

而每個工廠具體產出的實際產品是如下這樣產出的,


這個是ArrayList的,可以看到返回的產品就是一個私有的內部類。


這個是HashSet的,可以看到的返回的產品就不一樣了,是map的keySet。
這樣設計的原因是:我們在使用迭代器進行遍歷的時候方法都需要是一樣的,next還有hasNext,用於獲取下一個元素還有判斷是否有下一個元素,但是針對於不同的集合因為儲存的方式不一樣所以這兩個方法的實現肯定是不一樣的,所以設計成了這樣。
從MyBatis看抽象工廠
其實在Collection介面中我們已經可以看出抽象工廠的影子了,為了加深理解,我們再看看我們常見的ORM框架MyBatis中是怎麼樣的。其實我們很容易找到它,因為MyBatis使用Factory來進行命名。
PS:如果你對MyBatis框架還並不熟悉,建議熟練使用之後再進行學習。
首先我們可以看到有SqlSessionFactory這樣一個介面,裡面有openSession方法


然後我們可以看到它的實現一共有兩個類


我們用工廠模式的方式去描述的話,SqlSessionFactory介面就是我們的抽象工廠,這裡面有很多抽象出來的方法,也就是介面中包含的方法,有兩個實際的工廠需要去實現這樣的方法,同時生產出不同的產品。
然後我們再從產品的角度來說,工廠產出的產品這裡指的是SqlSession這個物件


這個物件本身也是一個介面,也就是說它也是一個抽象的產品


從圖中我們就可以看到,具體的產品也有兩種,這兩種正好對應了上說到的兩個工廠。
如果我們針對defalut工廠來看的話,大致的結構應該是這樣的:


而SqlSessionManager也是類似
產出的產品SqlSession是用於最終執行查詢修改等操作的,可見SqlSession在整個框架是非常重要的一環,而SqlSession的建立和維護管理就很重要了,而且SqlSession執行肯定需要配置檔案中的一些資訊,不是隨便new一個就完事了,所以在這裡使用工廠模式建立的意義也就出現了。
總結
工廠模式在實際中的使用還是挺常見的,在一些其他框架也有存在,比如常見的spring中。我們可以總結出,在建立一些物件的時候,如果建立的過程在重複,建立的過程比較複雜,建立的產品同類型多,那麼我們就可以考慮使用對應的工廠模式去解決。
同時在之前在基礎裡面說明了,產品的分類不要過多,否則如果一種產品一個工廠那麼那麼很容易導致類的爆炸增長。