Java設(shè)計(jì)模式中的工廠模式詳解
一、定義
工廠方法模式(Factory Method Pattern):創(chuàng)新型模式之一,簡(jiǎn)稱(chēng)工廠模式,通過(guò)定義工廠父類(lèi)負(fù)責(zé)定義創(chuàng)建對(duì)象的公共接口,而子類(lèi)則負(fù)責(zé)生成具體的對(duì)象。
二、UML類(lèi)圖
三、角色職責(zé)
- 抽象產(chǎn)品(Product):它是定義產(chǎn)品的接口,是工廠方法模式所創(chuàng)建對(duì)象的超類(lèi)型,也就是產(chǎn)品對(duì)象的公共父類(lèi)。
- 具體產(chǎn)品(Concrete Product):它實(shí)現(xiàn)了抽象產(chǎn)品接口,某種類(lèi)型的具體產(chǎn)品由專(zhuān)門(mén)的具體工廠創(chuàng)建,具體工廠和具體產(chǎn)品之間一一對(duì)應(yīng)。
- 抽象工廠(Factory):在抽象工廠類(lèi)中聲明了工廠方法(Factory Method),用于返回一個(gè)產(chǎn)品。抽象工廠是工廠方法模式的核心,所有創(chuàng)建對(duì)象的工廠類(lèi)都必須實(shí)現(xiàn)該接口。
- 具體工廠(Concrete Factory):它是抽象工廠類(lèi)的子類(lèi),實(shí)現(xiàn)了在抽象工廠中聲明的工廠方法,并可由客戶(hù)端調(diào)用,返回一個(gè)具體產(chǎn)品類(lèi)的實(shí)例。
四、代碼實(shí)現(xiàn)
前言:在簡(jiǎn)單工廠模式中,我們每需要增加一個(gè)品牌的籃球,就需要修改一次工廠,非常麻煩且復(fù)雜,違背了開(kāi)閉原則。在工廠方法模式中,這個(gè)缺陷得到了修復(fù)。我們將籃球工廠作為一個(gè)抽象工廠,每個(gè)品牌的籃球工廠去實(shí)現(xiàn)這個(gè)抽象工廠,籃球?qū)ο蟮膭?chuàng)建由每個(gè)工廠去負(fù)責(zé),當(dāng)我們需要新的品牌的籃球時(shí),只需要添加籃球工廠與籃球產(chǎn)品即可,提高了程序的擴(kuò)展性。
抽象籃球接口(抽象產(chǎn)品類(lèi) abstract Product)
public interface BasketBall { void shot(); }
阿迪達(dá)斯籃球(具體產(chǎn)品類(lèi) Concrete Product)
public class AdidasBasketBall implements BasketBall { @Override public void shot() { System.out.println("使用阿迪達(dá)斯籃球投籃"); } }
耐克籃球(具體產(chǎn)品類(lèi) Concrete Product)
public class NikeBasketBall implements BasketBall { @Override public void shot() { System.out.println("使用耐克籃球投籃"); } }
斯伯丁籃球(具體產(chǎn)品類(lèi) Concrete Product)
public class SpaldingBasketBall implements BasketBall { @Override public void shot() { System.out.println("使用斯伯丁籃球投籃"); } }
抽象籃球工廠接口(抽象工廠類(lèi) Factory)
public interface BasketBallFactory { public BasketBall make(); }
阿迪達(dá)斯籃球工廠(具體工廠類(lèi) Concrete Factory)
public class AdidasBasketBallFactory implements BasketBallFactory { @Override public BasketBall make() { return new AdidasBasketBall(); } }
耐克籃球工廠(具體工廠類(lèi) Concrete Factory)
public class NikeBasketBallFactory implements BasketBallFactory { @Override public BasketBall make() { return new NikeBasketBall(); } }
斯伯丁籃球工廠(具體工廠類(lèi) Concrete Factory)
public class SpaldingBasketBallFactory implements BasketBallFactory { @Override public BasketBall make() { return new SpaldingBasketBall(); } }
測(cè)試類(lèi)
public class FactoryMethodTest { public static void main(String[] args) { // 使用阿迪達(dá)斯籃球投籃 BasketBallFactory adidasBasketBallFactory = new AdidasBasketBallFactory(); adidasBasketBallFactory.make().shot(); // 使用耐克籃球投籃 BasketBallFactory nikeBasketBallFactory = new NikeBasketBallFactory(); nikeBasketBallFactory.make().shot(); // 使用斯伯丁籃球投籃 BasketBallFactory spaldingBasketBallFactory = new SpaldingBasketBallFactory(); spaldingBasketBallFactory.make().shot(); } }
五、源碼分析
工廠方法模式應(yīng)用的地方非常廣泛,在Spring中就有很多使用了工廠方法模式的地方。
其中AbstractApplicationContext就是ApplicationContext接口的實(shí)現(xiàn)抽象類(lèi)。
AbstractApplicationContext的子類(lèi)AbstractRefreshableApplicationContext就實(shí)現(xiàn)了這個(gè)抽象方法,使用了這個(gè)工廠方法去創(chuàng)建了實(shí)例。
這樣類(lèi)的設(shè)計(jì)與真正的實(shí)現(xiàn)之間其實(shí)是松耦合的,也正好符合了設(shè)計(jì)的開(kāi)閉原則。
六、優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 用戶(hù)只需要關(guān)心所需產(chǎn)品對(duì)應(yīng)的工廠,無(wú)需關(guān)心創(chuàng)建細(xì)節(jié)。
- 加入新產(chǎn)品 時(shí), 只需要添加一個(gè)具體工廠和具體產(chǎn)品 , 提高可擴(kuò)展性,符合開(kāi)閉原則。
- 工廠方法模式中 , 使用工廠類(lèi)創(chuàng)建產(chǎn)品對(duì)象 , 同時(shí)隱藏了具體的產(chǎn)品類(lèi)被實(shí)例化的細(xì)節(jié) 。
缺點(diǎn):
- 在添加新產(chǎn)品時(shí) , 除了編寫(xiě)新的產(chǎn)品類(lèi) , 還要編寫(xiě)該產(chǎn)品類(lèi)對(duì)應(yīng)的工廠類(lèi),增加系統(tǒng)復(fù)雜度。
七、適用場(chǎng)景
在日志記錄與訪問(wèn)的數(shù)據(jù)庫(kù)未知時(shí),會(huì)有較多的適用。
客戶(hù)端對(duì)需要對(duì)象的類(lèi)未知時(shí),抽象工廠類(lèi)通過(guò)其子類(lèi)來(lái)指定創(chuàng)建哪個(gè)對(duì)象。
通過(guò)多態(tài)性,在程序運(yùn)行時(shí)子類(lèi)覆蓋父類(lèi)對(duì)象,從而使得系統(tǒng)更容易擴(kuò)展。
八、總結(jié)
工廠方法模式中核心的工廠類(lèi)不再負(fù)責(zé)對(duì)相應(yīng)子類(lèi)的創(chuàng)建,而是聲明一個(gè)子工廠類(lèi)必須實(shí)現(xiàn)的接口,具體的實(shí)例化工作由子工廠類(lèi)去做,提高了程序的擴(kuò)展性,符合開(kāi)閉原則。
但在新增一個(gè)新產(chǎn)品時(shí),就要新增一個(gè)具體工廠和一個(gè)具體產(chǎn)品,會(huì)增加代碼量。
工廠方法模式克服了簡(jiǎn)單工廠違背開(kāi)放閉原則的缺點(diǎn),又保持了封裝對(duì)象創(chuàng)建過(guò)程的優(yōu)點(diǎn)。
到此這篇關(guān)于Java設(shè)計(jì)模式中的工廠模式詳解的文章就介紹到這了,更多相關(guān)Java工廠模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)現(xiàn)自動(dòng)生成縮略圖片
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)自動(dòng)生成縮略圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04springboot訪問(wèn)不存在的URL時(shí)的處理方法
在前后端分離的模式下,當(dāng)Spring Boot應(yīng)用接收到一個(gè)不存在的URL請(qǐng)求時(shí),通常希望返回一個(gè)固定的JSON字符串作為響應(yīng),以便前端能夠據(jù)此進(jìn)行相應(yīng)的處理,本文給大家介紹了springboot訪問(wèn)不存在的URL時(shí)的處理方法,需要的朋友可以參考下2024-12-12解決Spring Boot 多模塊注入訪問(wèn)不到j(luò)ar包中的Bean問(wèn)題
這篇文章主要介紹了解決Spring Boot 多模塊注入訪問(wèn)不到j(luò)ar包中的Bean問(wèn)題。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09Java使用FTPClient類(lèi)讀寫(xiě)FTP
這篇文章主要為大家詳細(xì)介紹了Java使用FTPClient類(lèi)讀寫(xiě)FTP的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04使用hutool進(jìn)行ftp文件下載和上傳詳細(xì)代碼示例
在開(kāi)發(fā)Java項(xiàng)目時(shí),FTP客戶(hù)端是經(jīng)常需要使用的工具,因?yàn)镕TP協(xié)議在文件傳輸方面有著廣泛的應(yīng)用,這篇文章主要給大家介紹了關(guān)于使用hutool進(jìn)行ftp文件下載和上傳的相關(guān)資料,需要的朋友可以參考下2024-02-02Java錯(cuò)誤問(wèn)題:找不到或無(wú)法加載主類(lèi)的解決
這篇文章主要介紹了Java錯(cuò)誤問(wèn)題:找不到或無(wú)法加載主類(lèi)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03Java算法之?dāng)?shù)組冒泡排序代碼實(shí)例講解
這篇文章主要介紹了Java算法之?dāng)?shù)組冒泡排序代碼實(shí)例講解,文中用代碼舉例講解的很清晰,有感興趣的同學(xué)可以研究下2021-03-03