深入理解Java設(shè)計(jì)模式之簡(jiǎn)單工廠(chǎng)模式
一、什么是簡(jiǎn)單工廠(chǎng)模式
簡(jiǎn)單工廠(chǎng)模式又稱(chēng)為靜態(tài)工廠(chǎng)模式,實(shí)質(zhì)是由一個(gè)工廠(chǎng)類(lèi)根據(jù)傳入的參數(shù),動(dòng)態(tài)決定應(yīng)該創(chuàng)建哪一個(gè)產(chǎn)品類(lèi)(這些產(chǎn)品類(lèi)繼承自一個(gè)父類(lèi)或接口)的實(shí)例。簡(jiǎn)單工廠(chǎng)模式的創(chuàng)建目標(biāo),所有創(chuàng)建的對(duì)象都是充當(dāng)這個(gè)角色的某個(gè)具體類(lèi)的實(shí)例。
其實(shí)就是將一個(gè)具體類(lèi)的實(shí)例化交給一個(gè)靜態(tài)工廠(chǎng)方法來(lái)執(zhí)行,它不屬于GOF的23種設(shè)計(jì)模式,但現(xiàn)實(shí)中卻經(jīng)常會(huì)用到,而且思想也非常簡(jiǎn)單。
二、簡(jiǎn)單工廠(chǎng)模式的結(jié)構(gòu)
簡(jiǎn)單工廠(chǎng)模式包含如下角色:
Factory
:工廠(chǎng)角色
Product
:抽象產(chǎn)品角色
ConcreteProduct
:具體產(chǎn)品角色
工廠(chǎng)角色(Creator) | 是簡(jiǎn)單工廠(chǎng)模式的核心,它負(fù)責(zé)實(shí)現(xiàn)創(chuàng)建所有具體產(chǎn)品類(lèi)的實(shí)例。工廠(chǎng)類(lèi)可以被外界直接調(diào)用,創(chuàng)建所需的產(chǎn)品對(duì)象。 |
抽象產(chǎn)品角色(Product) | 是所有具體產(chǎn)品角色的父類(lèi),它負(fù)責(zé)描述所有實(shí)例所共有的公共接口。 |
具體產(chǎn)品角色(Concrete Product) | 繼承自抽象產(chǎn)品角色,一般為多個(gè),是簡(jiǎn)單工廠(chǎng)模式的創(chuàng)建目標(biāo)。工廠(chǎng)類(lèi)返回的都是該角色的某一具體產(chǎn)品。 |
三、簡(jiǎn)單工廠(chǎng)模式的應(yīng)用場(chǎng)景
1.前幾天蘋(píng)果公司剛發(fā)布IPhone Xs和iPhone XR,那么問(wèn)題來(lái)了,蘋(píng)果公司的代工廠(chǎng)到底生產(chǎn)多少種尺寸的手機(jī)呢?
1.由工廠(chǎng)決定生產(chǎn)哪種型號(hào)的的手機(jī),蘋(píng)果公司的工廠(chǎng)就是一個(gè)工廠(chǎng)類(lèi),是簡(jiǎn)單工廠(chǎng)模式的核心類(lèi)。
2.iPhoneX、iPhoneXs、iphoneXr都是蘋(píng)果手機(jī),只是型號(hào)不同。蘋(píng)果手機(jī)類(lèi)滿(mǎn)足抽象的定義,各個(gè)型號(hào)的手機(jī)類(lèi)是其具體實(shí)現(xiàn)。
2.考慮一個(gè)簡(jiǎn)單的軟件應(yīng)用場(chǎng)景,一個(gè)軟件系統(tǒng)可以提供多個(gè)外觀(guān)不同的按鈕(如圓形按鈕、矩形按鈕、菱形按鈕等),這些按鈕都源自同一個(gè)基類(lèi),不過(guò)在繼承基類(lèi)后不同的子類(lèi)修改了部分屬性從而使得它們可以呈現(xiàn)不同的外觀(guān),如果我們希望在使用這些按鈕時(shí),不需要知道這些具體按鈕類(lèi)的名字,只需要知道表示該按鈕類(lèi)的一個(gè)參數(shù),并提供一個(gè)調(diào)用方便的方法,把該參數(shù)傳入方法即可返回一個(gè)相應(yīng)的按鈕對(duì)象,此時(shí),就可以使用簡(jiǎn)單工廠(chǎng)模式。
在以下情況下可以使用簡(jiǎn)單工廠(chǎng)模式:
工廠(chǎng)類(lèi)負(fù)責(zé)創(chuàng)建的對(duì)象比較少:由于創(chuàng)建的對(duì)象較少,不會(huì)造成工廠(chǎng)方法中的業(yè)務(wù)邏輯太過(guò)復(fù)雜。
客戶(hù)端只知道傳入工廠(chǎng)類(lèi)的參數(shù),對(duì)于如何創(chuàng)建對(duì)象不關(guān)心:客戶(hù)端既不需要關(guān)心創(chuàng)建細(xì)節(jié),甚至連類(lèi)名都不需要記住,只需要知道類(lèi)型所對(duì)應(yīng)的參數(shù)。
四、簡(jiǎn)單工廠(chǎng)模式和工廠(chǎng)方法模式區(qū)別
簡(jiǎn)單工廠(chǎng)模式:
(1)工廠(chǎng)類(lèi)負(fù)責(zé)創(chuàng)建的對(duì)象比較少,由于創(chuàng)建的對(duì)象較少,不會(huì)造成工廠(chǎng)方法中的業(yè)務(wù)邏輯太過(guò)復(fù)雜。
(2)客戶(hù)端只知道傳入工廠(chǎng)類(lèi)的參數(shù),對(duì)于如何創(chuàng)建對(duì)象并不關(guān)心。
工廠(chǎng)方法模式:
(1)客戶(hù)端不知道它所需要的對(duì)象的類(lèi)。
(2)抽象工廠(chǎng)類(lèi)通過(guò)其子類(lèi)來(lái)指定創(chuàng)建哪個(gè)對(duì)象。
五、簡(jiǎn)單工廠(chǎng)模式和策略模式的異同
策略模式和簡(jiǎn)單工廠(chǎng)模式看起來(lái)非常相似,都是通過(guò)多態(tài)來(lái)實(shí)現(xiàn)不同子類(lèi)的選取,這種思想應(yīng)該是從程序的整體來(lái)看得出的。
如果從使用這兩種模式的角度來(lái)看的話(huà),我們會(huì)發(fā)現(xiàn)在簡(jiǎn)單工廠(chǎng)模式中我們只需要傳遞相應(yīng)的條件就能得到想要的一個(gè)對(duì)象,然后通過(guò)這個(gè)對(duì)象實(shí)現(xiàn)算法的操作。
而策略模式,使用時(shí)必須首先創(chuàng)建一個(gè)想使用的類(lèi)對(duì)象,然后將該對(duì)象最為參數(shù)傳遞進(jìn)去,通過(guò)該對(duì)象調(diào)用不同的算法。
在簡(jiǎn)單工廠(chǎng)模式中實(shí)現(xiàn)了通過(guò)條件選取一個(gè)類(lèi)去實(shí)例化對(duì)象,策略模式則將選取相應(yīng)對(duì)象的工作交給模式的使用者,它本身不去做選取工作。
結(jié)合下面的代碼和下面的釋義不難看出,其實(shí)兩個(gè)的差別很微妙,Factory是直接創(chuàng)建具體的對(duì)象并用該對(duì)象去執(zhí)行相應(yīng)的動(dòng)作,而Context將這個(gè)操作給了Context類(lèi),沒(méi)有創(chuàng)建具體的對(duì)象,實(shí)現(xiàn)的代碼的進(jìn)一步封裝,客戶(hù)端代碼并不需要知道具體的實(shí)現(xiàn)過(guò)程。
六、簡(jiǎn)單工廠(chǎng)模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
工廠(chǎng)類(lèi)是整個(gè)模式的關(guān)鍵.包含了必要的邏輯判斷,根據(jù)外界給定的信息,決定究竟應(yīng)該創(chuàng)建哪個(gè)具體類(lèi)的對(duì)象.
通過(guò)使用工廠(chǎng)類(lèi),外界可以從直接創(chuàng)建具體產(chǎn)品對(duì)象的尷尬局面擺脫出來(lái),僅僅需要負(fù)責(zé)“消費(fèi)”對(duì)象就可以了。
而不必管這些對(duì)象究竟如何創(chuàng)建及如何組織的.明確了各自的職責(zé)和權(quán)利,有利于整個(gè)軟件體系結(jié)構(gòu)的優(yōu)化。
缺點(diǎn):
由于工廠(chǎng)類(lèi)集中了所有實(shí)例的創(chuàng)建邏輯,違反了開(kāi)閉原則,將全部創(chuàng)建邏輯集中到了一個(gè)工廠(chǎng)類(lèi)中;
它所能創(chuàng)建的類(lèi)只能是事先考慮到的,如果需要添加新的類(lèi),則就需要改變工廠(chǎng)類(lèi)了。
當(dāng)系統(tǒng)中的具體產(chǎn)品類(lèi)不斷增多時(shí)候,可能會(huì)出現(xiàn)要求工廠(chǎng)類(lèi)根據(jù)不同條件創(chuàng)建不同實(shí)例的需求.
這種對(duì)條件的判斷和對(duì)具體產(chǎn)品類(lèi)型的判斷交錯(cuò)在一起,很難避免模塊功能的蔓延,對(duì)系統(tǒng)的維護(hù)和擴(kuò)展非常不利;
開(kāi)閉原則定義:一個(gè)軟件實(shí)體如類(lèi)、模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。
開(kāi)放-封閉原則的意思就是說(shuō),你設(shè)計(jì)的時(shí)候,時(shí)刻要考慮,盡量讓這個(gè)類(lèi)是足夠好,寫(xiě)好了就不要去修改了,如果新需求來(lái),我們?cè)黾右恍╊?lèi)就完事了,原來(lái)的代碼能不動(dòng)則不動(dòng)。這個(gè)原則有兩個(gè)特性,一個(gè)是說(shuō)“對(duì)于擴(kuò)展是開(kāi)放的”,另一個(gè)是說(shuō)“對(duì)于更改是封閉的”。面對(duì)需求,對(duì)程序的改動(dòng)是通過(guò)增加新代碼進(jìn)行的,而不是更改現(xiàn)有的代碼。這就是“開(kāi)放-封閉原則”的精神所在。
七、簡(jiǎn)單工廠(chǎng)模式的實(shí)現(xiàn)
首先創(chuàng)建一個(gè)"蘋(píng)果手機(jī)"類(lèi),定義一個(gè)獲取手機(jī)尺寸的方法
//蘋(píng)果手機(jī) public abstract class ApplePhone { //獲取尺寸 protected abstract void getSize(); }
蘋(píng)果手機(jī)不同型號(hào)的"手機(jī)類(lèi)"。
public class IphoneX:ApplePhone{ public void getSize() { Console.WriteLine("iPhoneX屏幕:3.5英寸"); } } public class IphoneXs:ApplePhone{ public void getSize() { Console.WriteLine("iPhoneX屏幕:4.5英寸"); } } public class IphoneXR:ApplePhone{ public void getSize() { Console.WriteLine("iPhoneX屏幕:5.5英寸"); } }
建立一個(gè)"工廠(chǎng)類(lèi)"生產(chǎn)不同型號(hào)的"手機(jī)對(duì)象"。
//蘋(píng)果工廠(chǎng) public class AppleFactory { public static ApplePhone createPhone(String model){ ApplePhone applePhone = null; switch (model) { case"iPhoneX": applePhone = new IphoneX(); break; case"iPhoneXs": applePhone = new IphoneXs(); break; case"iPhoneXr": applePhone = new IphoneXR(); break; default: break; } returnapplePhone; } }
最后是客戶(hù)端測(cè)試類(lèi)
public class Client { public static void main(String[] args) { ApplePhone applePhone ; applePhone = AppleFactory.createPhone("iPhoneX"); applePhone.getSize(); applePhone = AppleFactory.createPhone("iPhoneXs"); applePhone.getSize(); applePhone = AppleFactory.createPhone("iPhoneXr"); applePhone.getSize(); } }
八、總結(jié)
創(chuàng)建型模式對(duì)類(lèi)的實(shí)例化過(guò)程進(jìn)行了抽象,能夠?qū)?duì)象的創(chuàng)建與對(duì)象的使用過(guò)程分離。
簡(jiǎn)單工廠(chǎng)模式又稱(chēng)為靜態(tài)工廠(chǎng)方法模式,它屬于類(lèi)創(chuàng)建型模式。在簡(jiǎn)單工廠(chǎng)模式中,可以根據(jù)參數(shù)的不同返回不同類(lèi)的實(shí)例。
簡(jiǎn)單工廠(chǎng)模式專(zhuān)門(mén)定義一個(gè)類(lèi)來(lái)負(fù)責(zé)創(chuàng)建其他類(lèi)的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的父類(lèi)。
簡(jiǎn)單工廠(chǎng)模式包含三個(gè)角色:工廠(chǎng)角色負(fù)責(zé)實(shí)現(xiàn)創(chuàng)建所有實(shí)例的內(nèi)部邏輯;抽象產(chǎn)品角色是所創(chuàng)建的所有對(duì)象的父類(lèi),負(fù)責(zé)描述所有實(shí)例所共有的公共接口;具體產(chǎn)品角色是創(chuàng)建目標(biāo),所有創(chuàng)建的對(duì)象都充當(dāng)這個(gè)角色的某個(gè)具體類(lèi)的實(shí)例。
簡(jiǎn)單工廠(chǎng)模式的要點(diǎn)在于:當(dāng)你需要什么,只需要傳入一個(gè)正確的參數(shù),就可以獲取你所需要的對(duì)象,而無(wú)須知道其創(chuàng)建細(xì)節(jié)。
簡(jiǎn)單工廠(chǎng)模式最大的優(yōu)點(diǎn)在于實(shí)現(xiàn)對(duì)象的創(chuàng)建和對(duì)象的使用分離,將對(duì)象的創(chuàng)建交給專(zhuān)門(mén)的工廠(chǎng)類(lèi)負(fù)責(zé),但是其最大的缺點(diǎn)在于工廠(chǎng)類(lèi)不夠靈活,增加新的具體產(chǎn)品需要修改工廠(chǎng)類(lèi)的判斷邏輯代碼,而且產(chǎn)品較多時(shí),工廠(chǎng)方法代碼將會(huì)非常復(fù)雜。
簡(jiǎn)單工廠(chǎng)模式適用情況包括:工廠(chǎng)類(lèi)負(fù)責(zé)創(chuàng)建的對(duì)象比較少;客戶(hù)端只知道傳入工廠(chǎng)類(lèi)的參數(shù),對(duì)于如何創(chuàng)建對(duì)象不關(guān)心。
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
SpringBoot詳細(xì)講解如何創(chuàng)建及刷新Spring容器bean
前面看spring源碼時(shí)可以發(fā)現(xiàn)refresh()方法十分重要。在這個(gè)方法中會(huì)加載beanDefinition,同時(shí)創(chuàng)建bean對(duì)象。那么在springboot中有沒(méi)有使用這個(gè)refresh()方法呢2022-06-06Spring boot整合Springfox生成restful的在線(xiàn)api文檔
這篇文章主要為大家介紹了Spring boot整合Springfox生成restful在線(xiàn)api文檔,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03J2EE Servlet上傳文件到服務(wù)器并相應(yīng)顯示功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了J2EE Servlet上傳文件到服務(wù)器,并相應(yīng)顯示,在文中上傳方式使用的是post不能使用get,具體實(shí)例代碼大家參考下本文2018-07-07SpringCloud的JPA連接PostgreSql的教程
這篇文章主要介紹了SpringCloud的JPA接入PostgreSql 教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-06-06spring mvc+localResizeIMG實(shí)現(xiàn)HTML5端圖片壓縮上傳
這篇文章主要為大家詳細(xì)介紹了使用spring mvc+localResizeIMG實(shí)現(xiàn)HTML5端圖片壓縮上傳,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04擴(kuò)展tk.mybatis的流式查詢(xún)功能實(shí)現(xiàn)
mybatis查詢(xún)默認(rèn)是一次獲取全部,如果數(shù)據(jù)過(guò)于龐大,就會(huì)導(dǎo)致OOM問(wèn)題,本文就介紹了tk.mybatis 流式查詢(xún),具有一定的參考價(jià)值,感興趣的可以了解一下2021-12-12