設(shè)計模式案例分析-github
一去团、前言
工廠模式分為工廠方法(又稱簡單工廠)模式寞秃、抽象工廠模式。為方便講解踱葛,工廠方法或者簡單工廠統(tǒng)一命名為工廠方法模式丹莲。本篇先講解工廠方法模式
二、工廠方法模式之簡單版——簡單工廠
定義:?靜態(tài)實例化符合我們要求的實例
特點:? 對于簡單的工廠方法尸诽,可以理解為就是一個創(chuàng)建對象的工具類(工廠方法的簡化版)
案例1: android中的BitmapFactory, 創(chuàng)建bitmap的過程甥材,客戶端不需要知道,創(chuàng)建的過程由BitmapFactory處理性含,掩藏了創(chuàng)建bitmap的細(xì)節(jié)洲赵。
? ? ? ? ? android中的XmlPullParserFactory,創(chuàng)建解析器
案例2:比如創(chuàng)建地圖商蕴,定義了創(chuàng)建地圖的統(tǒng)一規(guī)范板鬓,具體實現(xiàn)你可以創(chuàng)建高德地圖、蘋果地圖等究恤,使用簡單工廠模式俭令,客戶端只要傳入要創(chuàng)建什么類型的地圖,工廠就幫你創(chuàng)建好部宿,掩藏了內(nèi)部創(chuàng)建對象的細(xì)節(jié)
類圖結(jié)構(gòu):
代碼案例見:設(shè)計模式案例分析-github
總結(jié):靜態(tài)實例化符合我們要求的實例(本質(zhì)核心:降低客戶端與要創(chuàng)建對象的耦合)
分析:?考慮有如下需求: 百度地圖有全景圖抄腔,高德地圖沒有的功能,要怎么設(shè)計???
由于簡單工廠模式理张,有點太過簡單這時候使用簡單工廠就不是很好用了赫蛇,因為MapViewFactory是統(tǒng)一的工廠入口,返回創(chuàng)建的是抽象對象雾叭,如果需要在繼續(xù)的簡單工廠改的話悟耘,就需要在MapViewFactory中修改代碼,而高德又沒有织狐,案例就不應(yīng)該寫在公用的MapViewFactory中暂幼。
因此引入了工廠方法模式,即需要對工廠進(jìn)行抽象(使用接口)移迫,修改后只要把新增的需求寫在具體的工廠中即可,彌補了簡單工廠方法對修改開放的弱點旺嬉。
三、 工廠方法模式之規(guī)范版——工廠方法
特點: 1厨埋、針對單個產(chǎn)品抽象
? ? ? ? ?2邪媳、工廠的抽象方法中只有一條流水線
定義: 定義一個用戶創(chuàng)建對象的統(tǒng)計接口,具體實現(xiàn)由子類實現(xiàn)
分析:?考慮有如下需求: 百度地圖有全景圖,高德地圖沒有的功能雨效,要怎么設(shè)計???
由于簡單工廠模式迅涮,有點太過簡單這時候使用簡單工廠就不是很好用了,因為MapViewFactory是統(tǒng)一的工廠入口徽龟,返回創(chuàng)建的是抽象對象叮姑,如果需要在繼續(xù)的簡單工廠改的話,就需要在MapViewFactory中修改代碼顿肺,而高德又沒有戏溺,案例就不應(yīng)該寫在公用的MapViewFactory中渣蜗。
因此引入了工廠方法模式屠尊,即需要對工廠進(jìn)行抽象(使用接口),修改后只要把新增的需求寫在具體的工廠中即可,?彌補了簡單工廠方法對修改開放的弱點耕拷。
核心: 掩藏創(chuàng)建對象的細(xì)節(jié)讼昆,封裝了統(tǒng)一創(chuàng)建的對象,后續(xù)要修改擴(kuò)展就容易了
案例:? 比如創(chuàng)建地圖骚烧,定義了創(chuàng)建地圖的統(tǒng)一規(guī)范浸赫,具體實現(xiàn)你可以創(chuàng)建高德地圖、蘋果地圖等赃绊。
類圖結(jié)構(gòu):?
分析: 角色既峡?
1、抽象工廠IMapFactory——定義了創(chuàng)建對象的規(guī)范碧查,具體創(chuàng)建什么對象由子類實現(xiàn)
2运敢、具體工廠BaiduMapFactory——定義具體創(chuàng)建對象的流程(可沈略,通過抽象工程類外部傳入要創(chuàng)建對象的類型忠售,返回具體的對象传惠,當(dāng)然不建議這樣做,因為這樣客戶端還是依賴了具體的類型(因為傳參了稻扬,具體可下載github上的demo查閱)
3卦方、抽象產(chǎn)品IMapView——定義工廠所要創(chuàng)建產(chǎn)品共有的性質(zhì)
4、具體產(chǎn)品BaiduMapView——定義工廠所要創(chuàng)建的具體產(chǎn)品
可以看到泰佳,上圖上半部分是工廠抽象和實現(xiàn)體系盼砍,下半部分是產(chǎn)品抽象和實現(xiàn)體系,其中工廠體系依賴于產(chǎn)品體系逝她,每一個工廠負(fù)責(zé)創(chuàng)造一種產(chǎn)品衬廷,這就省去了簡單工廠中的elseif判斷,由客戶端決定實例化一個特定的工廠去創(chuàng)建相應(yīng)的產(chǎn)品汽绢。
好處:這樣進(jìn)一步抽象化的好處是使得工廠方法模式可以使系統(tǒng)在不修改具體工廠角色的情況下引進(jìn)新的產(chǎn)品吗跋,即這時候如果新增了一個xx的地圖,只需要新建一個xx地圖,以及xx地圖的工廠即可實現(xiàn)跌宛,而不需要在原來代碼上進(jìn)行修改酗宋,做到了對擴(kuò)展開放,對修改關(guān)閉的原則疆拘。
案例: android或者java中有哪些場景使用了工廠方法?
? ? ? ? 1蜕猫、java中的jdbc設(shè)計(java數(shù)據(jù)庫連接)
2、android/java中的集合
分析:??工廠方法模式就是提供一個抽象的工廠哎迄,一個抽象的產(chǎn)品回右,在上述當(dāng)中相當(dāng)于Driver(數(shù)據(jù)庫連接工廠)和Connection(抽象產(chǎn)品),實現(xiàn)的一方需要提供一個具體的工廠類(比如mysql驅(qū)動)和一個具體的產(chǎn)品(比如mysql數(shù)據(jù)庫連接).
? ? ? ? ? Iterable相當(dāng)于抽象工廠定義漱挚,Iterator相當(dāng)于抽象產(chǎn)品翔烁,ArrayList、HashSet等是具體的工廠旨涝,產(chǎn)生的迭代器是具體的產(chǎn)品蹬屹。
疑惑:??各位可能會說,不對啊白华,這和我們剛才理解的不太一樣啊慨默,按照剛才的說法,我們不是應(yīng)該直接使用iterable和iterator嗎弧腥?這樣多牛X厦取,我們不依賴于具體產(chǎn)品了」芴拢可是sun或者說oracle為了集合框架給你提供了這么多具備各個特性的集合虾攻,你只用iterator和iterable,估計當(dāng)初參與設(shè)計集合框架的人都要氣的去shi了抛蚤。台谢。
? ? ? ? 上述這便是工廠方法模式另外一種用法了,剛才因為我們不關(guān)心真正的產(chǎn)品是什么岁经,所以我們直接使用抽象接口操作朋沮。但是我們使用iterable和iterator的時候,我們是關(guān)心真正產(chǎn)品的特性的缀壤,所以為了使用產(chǎn)品的特性樊拓,我們就需要使用產(chǎn)品特有的接口了,比如特殊的SortedSet可排序塘慕,比如ArrayList可以有重復(fù)元素筋夏,可以根據(jù)索引獲取元素等等。當(dāng)然你依然是可以使用iterable和iterator的图呢,但是不管你用什么条篷,在這種場景下骗随,產(chǎn)品是你自己選的。
總結(jié): 什么場景使用工廠方法模式?
? ? 1赴叹、在工廠的抽象中鸿染,只針對一條流水線,一個產(chǎn)品乞巧,比如只創(chuàng)建地圖,? 即我們需要一個產(chǎn)品幫我們完成一項任務(wù)涨椒,但是這個產(chǎn)品有可能有很多品牌(像這里的mysql,oracle)绽媒,為了保持我們對產(chǎn)品操作的一致性蚕冬,我們就可能要用到工廠方法模式,
比如我們需要直播sdk來幫我們完成直播是辕,但是直播可能有很多種“產(chǎn)商", 比如騰訊云直播囤热、阿里直播等,就可以考慮使用工廠方法模式免糕,抽象直播這一層赢乓,具體的創(chuàng)建由具體的工廠來實現(xiàn)忧侧。
缺點: 需要大量的具體工廠和具體產(chǎn)品石窑,當(dāng)然也可以使用泛型來規(guī)避具體的工廠(這種個人感覺不建議使用,因為客戶端對具體的產(chǎn)品依賴蚓炬,傳入了參數(shù))
四松逊、工廠模式——抽象工廠
定義:? 為創(chuàng)建一組相關(guān)或相互依賴的對象提供一個接口,而且無需指定他們的具體類肯夏。
通俗理解: 有多條流水線
類圖結(jié)構(gòu):?
下面給出本文所有代碼的github鏈接: