大戰設計模式(第二季)【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中。我們可以總結出,在創建一些對象的時候,如果創建的過程在重復,創建的過程比較復雜,創建的產品同類型多,那麽我們就可以考慮使用對應的工廠模式去解決。
同時在之前在基礎裏面說明了,產品的分類不要過多,否則如果一種產品一個工廠那麽那麽很容易導致類的爆炸增長。
大戰設計模式(第二季)【1】———— 從源碼看工廠模式