Java設(shè)計(jì)模式——工廠設(shè)計(jì)模式詳解
工廠模式:主要用來(lái)實(shí)例化有共同接口的類,工廠模式可以動(dòng)態(tài)決定應(yīng)該實(shí)例化那一個(gè)類。
工廠模式的形態(tài)
工廠模式主要用一下幾種形態(tài):
1:簡(jiǎn)單工廠(Simple Factory)。
2:工廠方法(Factory Method)。
3:抽象工廠(Abstract Factory)。
簡(jiǎn)單工廠(Simple Factory)
又叫靜態(tài)工廠,是工廠模式三中狀態(tài)中結(jié)構(gòu)最為簡(jiǎn)單的。主要有一個(gè)靜態(tài)方法,用來(lái)接受參數(shù),并根據(jù)參數(shù)來(lái)決定返回實(shí)現(xiàn)同一接口的不同類的實(shí)例。我們來(lái)看一個(gè)具體的例子:
假設(shè)一家工廠,幾生產(chǎn)洗衣機(jī),有生產(chǎn)冰箱,還有空調(diào)等等..
我們先為所有產(chǎn)品定義一個(gè)共同的產(chǎn)品接口
public interface Product{}
接著我們讓這個(gè)工廠的所有產(chǎn)品都必須實(shí)現(xiàn)此接口
public class Washer implements Product{
public Washer(){
System.out.println("洗衣機(jī)被制造了");
}
}
public class Icebox implements Product{
public Icebox(){
System.out.println("冰箱被制造了");
}
}
public class AirCondition implements Product{
public Icebox(){
System.out.println("空調(diào)被制造了");
}
}
接下來(lái)我們來(lái)寫一個(gè)工廠類,有它來(lái)負(fù)責(zé)生產(chǎn)以上的產(chǎn)品
public class SimpleFactory {
public static Product factory(String productName) throws Exception{
if(productName.equals("Washer")){
return new Washer();
}else if(productName.equals("Icebox")){
return new Icebox();
}else if(productName.equals("AirCondition")){
return new AirCondition();
}else{
throw new Exception("沒(méi)有該產(chǎn)品");
}
}
}
好了,有了這個(gè)工廠類,我們就可以開(kāi)始下定單了,SimpleFactory將根據(jù)不同的定單類決定生產(chǎn)什么產(chǎn)品。
public static void main(String[] args) {
try {
SimpleFactory.factory("Washer");
SimpleFactory.factory("Icebox");
SimpleFactory.factory("AirCondition");
} catch (Exception e) {
e.printStackTrace();
}
}
由上面的代碼可以看出,簡(jiǎn)單工廠的核心就是一個(gè)SimpleFactory類,他擁有必要的邏輯判斷能力和所有產(chǎn)品的創(chuàng)建權(quán)利,我們只需要向把定單給他,就能得到我們想要的產(chǎn)品。這使用起來(lái)似乎非常方便。
但,實(shí)際上,這個(gè)SimpleFactory有很多的局限。首先,我們每次想要增加一種新產(chǎn)品的時(shí)候,都必須修改SimpleFactory的原代碼。其次,當(dāng)我們擁有很多很多產(chǎn)品的時(shí)候,而且產(chǎn)品之間又存在復(fù)雜的層次關(guān)系的時(shí)候,這個(gè)類必須擁有復(fù)雜的邏輯判斷能力,其代碼量也將不斷地激增,這對(duì)以后的維護(hù)簡(jiǎn)直就是恐怖兩個(gè)字...
還有就是,整個(gè)系統(tǒng)都嚴(yán)重依賴SimpleFactory類,只要SimpleFactory類一出問(wèn)題,系統(tǒng)就進(jìn)入不能工作的狀態(tài),這也是最為致命的一點(diǎn)....
以上的不足將在工廠模式的另外兩種狀態(tài)中得到解決。
工廠方法(Factory Method)
上面的代碼告訴我們,簡(jiǎn)單工廠并不簡(jiǎn)單,它是整個(gè)模式的核心,一旦他出了問(wèn)題,整個(gè)模式都將受影響而不能工作,為了降低風(fēng)險(xiǎn)和為日后的維護(hù)、擴(kuò)展做準(zhǔn)備,我們需要對(duì)它進(jìn)行重構(gòu),引入工廠方法。
工廠方法為工廠類定義了接口,用多態(tài)來(lái)削弱了工廠類的職能,以下是工廠接口的定義:
public interface Factory{
public Product create();
}
我們?cè)賮?lái)定義一個(gè)產(chǎn)品接口
public interface Product{}
一下是實(shí)現(xiàn)了產(chǎn)品接口的產(chǎn)品類
public class Washer implements Product{
public Washer(){
System.out.println("洗衣機(jī)被制造了");
}
}
public class Icebox implements Product{
public Icebox(){
System.out.println("冰箱被制造了");
}
}
public class AirCondition implements Product{
public Icebox(){
System.out.println("空調(diào)被制造了");
}
}
接下來(lái),就是工廠方法的核心部分,也就是具體創(chuàng)建產(chǎn)品對(duì)象的具體工廠類,
//創(chuàng)建洗衣機(jī)的工廠
public class CreateWasher implements Factory{
public Product create(){
return new Washer();
}
}
//創(chuàng)建冰箱的工廠
public class CreateIcebox implements Factory{
public Product create(){
return new Icebox();
}
}
//創(chuàng)建空調(diào)的工廠
public class CreateAirCondition implements Factory{
public Product create(){
return new AirCondition();
}
}
從上面創(chuàng)建產(chǎn)品對(duì)象的代碼可以看出,工廠方法和簡(jiǎn)單工廠的主要區(qū)別是,簡(jiǎn)單工廠是把創(chuàng)建產(chǎn)品的職能都放在一個(gè)類里面,而工廠方法則把不同的產(chǎn)品放在實(shí)現(xiàn)了工廠接口的不同工廠類里面,這樣就算其中一個(gè)工廠類出了問(wèn)題,其他工廠類也能正常工作,互相不受影響,以后增加新產(chǎn)品,也只需要新增一個(gè)實(shí)現(xiàn)工廠接口工廠類,就能達(dá)到,不用修改已有的代碼。但工廠方法也有他局限的地方,那就是當(dāng)面對(duì)的產(chǎn)品有復(fù)雜的等級(jí)結(jié)構(gòu)的時(shí)候,例如,工廠除了生產(chǎn)家電外產(chǎn)品,還生產(chǎn)手機(jī)產(chǎn)品,這樣一來(lái)家電是手機(jī)就是兩大產(chǎn)品家族了,這兩大家族下面包含了數(shù)量眾多的產(chǎn)品,每個(gè)產(chǎn)品又有多個(gè)型號(hào),這樣就形成了一個(gè)復(fù)雜的產(chǎn)品樹(shù)了。如果用工廠方法來(lái)設(shè)計(jì)這個(gè)產(chǎn)品家族系統(tǒng),就必須為每個(gè)型號(hào)的產(chǎn)品創(chuàng)建一個(gè)對(duì)應(yīng)的工廠類,當(dāng)有數(shù)百種甚至上千種產(chǎn)品的時(shí)候,也必須要有對(duì)應(yīng)的上百成千個(gè)工廠類,這就出現(xiàn)了傳說(shuō)的類爆炸,對(duì)于以后的維護(hù)來(lái)說(shuō),簡(jiǎn)直就是一場(chǎng)災(zāi)難.....
抽象工廠(Factory Method)
抽象工廠:意的意圖在于創(chuàng)建一系列互相關(guān)聯(lián)或互相依賴的對(duì)象。<<Java設(shè)計(jì)模式>>
我自己覺(jué)得抽象工廠是在工廠方法的基礎(chǔ)上引進(jìn)了分類管理的概念....
工廠方法用來(lái)創(chuàng)建一個(gè)產(chǎn)品,它沒(méi)有分類的概念,而抽象工廠則用于創(chuàng)建一系列產(chǎn)品,所以產(chǎn)品分類成了抽象工廠的重點(diǎn),
我們繼續(xù)用上面的例子來(lái)說(shuō)明:
工廠生產(chǎn)的所有產(chǎn)品都用都用大寫字母來(lái)標(biāo)明它們的型號(hào),比如冰箱,就有“冰箱-A",“冰箱-B",同樣,其他的產(chǎn)品也都是遵守這個(gè)編號(hào)規(guī)則,于是就有了一下產(chǎn)品家族樹(shù)
冰箱:
冰箱-A
冰箱-B
洗衣機(jī):
洗衣機(jī)-A
洗衣機(jī)-B
我們可以為冰箱和洗衣機(jī)分別定義兩個(gè)產(chǎn)品接口,以對(duì)他們進(jìn)行分類
//洗衣機(jī)接口
public interface Washer{
}
//冰箱接口
public interface Icebox{
}
接著,我們分別創(chuàng)建這兩個(gè)接口的具體產(chǎn)品
//洗衣機(jī)-A
public class WasherA implements Washer{
public WasherA(){
System.out.println("洗衣機(jī)-A被制造了");
}
}
//洗衣機(jī)-B
public class WasherB implements Washer{
public WasherB(){
System.out.println("洗衣機(jī)-B被制造了");
}
}
//冰箱-A
public class IceboxA implements Icebox{
public IceboxA(){
System.out.println("冰箱-A被制造了");
}
}
//冰箱-B
public class IceboxB implements Icebox{
public IceboxB(){
System.out.println("冰箱-B被制造了");
}
}
到此,產(chǎn)品部分我們準(zhǔn)備好了,接下來(lái)我們來(lái)處理工廠部分,我們先來(lái)定義工廠行為接口
public interface Factory{
public Washer createWasher();
public Icebox createIcebox();
}
接下來(lái)我創(chuàng)造具體的工廠類,我們根據(jù)上面產(chǎn)品的接口,把型號(hào)A的產(chǎn)品分為一類,由一個(gè)工廠來(lái)管理,把型號(hào)為B的產(chǎn)品有另一個(gè)工廠管理,根據(jù)這個(gè)分類,我們可以實(shí)現(xiàn)如下的兩個(gè)具體工廠類
//創(chuàng)建型號(hào)為A的產(chǎn)品工廠
public class FactoryA implements Factory{
//創(chuàng)建洗衣機(jī)-A
public Washer createWasher(){
return new WasherA();
}
//創(chuàng)建冰箱-A
public Icebox createIcebox(){
return new IceboxA();
}
}
//創(chuàng)建型號(hào)為B的產(chǎn)品工廠
public class FactoryB implements Factory{
//創(chuàng)建洗衣機(jī)-B
public Washer createWasher(){
return new WasherB();
}
//創(chuàng)建冰箱-B
public Icebox createIcebox(){
return new IceboxB();
}
}
這樣,我們的抽象工廠就完成了。有上面可以看出,在運(yùn)用上我覺(jué)得工廠方法和抽象工廠,都有自己的應(yīng)用場(chǎng)景,并沒(méi)有什么優(yōu)劣之分,但在應(yīng)用抽象工廠之前,要先對(duì)創(chuàng)建的對(duì)象進(jìn)行系統(tǒng)的分類,這點(diǎn)很重要,好的產(chǎn)品分類規(guī)則能為具體工廠類的選擇調(diào)用和以后的擴(kuò)展提供清晰的思路.
總結(jié)
以上就是本文關(guān)于Java設(shè)計(jì)模式——工廠設(shè)計(jì)模式詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:Java設(shè)計(jì)模式之訪問(wèn)者模式使用場(chǎng)景及代碼示例、Java設(shè)計(jì)模式筆記之抽象工廠代碼示例等,有什么問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。感謝朋友們對(duì)本站的支持!
相關(guān)文章
Spring MVC+mybatis實(shí)現(xiàn)注冊(cè)登錄功能
這篇文章主要為大家詳細(xì)介紹了Spring MVC+mybatis實(shí)現(xiàn)注冊(cè)登錄功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Spring 開(kāi)發(fā)之組件賦值的實(shí)現(xiàn)方法
這篇文章主要介紹了Spring 開(kāi)發(fā)之組件賦值的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
java實(shí)現(xiàn)圖片裁切的工具類實(shí)例
這篇文章主要介紹了java實(shí)現(xiàn)圖片裁切的工具類實(shí)例,涉及Java針對(duì)圖片的讀取、修改等相關(guān)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
mybatis-plus IdWorker生成的Id和返回給前臺(tái)的不一致的解決
這篇文章主要介紹了mybatis-plus IdWorker生成的Id和返回給前臺(tái)的不一致的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Spring?Aop+Redis實(shí)現(xiàn)優(yōu)雅記錄接口調(diào)用情況
通常情況下,開(kāi)發(fā)完一個(gè)接口,無(wú)論是在測(cè)試階段還是生產(chǎn)上線,我們都需要對(duì)接口的執(zhí)行情況做一個(gè)監(jiān)控,所以本文為大家整理了Spring統(tǒng)計(jì)接口調(diào)用的多種方法,希望對(duì)大家有所幫助2023-06-06
解決mybatis使用foreach批量insert異常的問(wèn)題
這篇文章主要介紹了解決mybatis使用foreach批量insert異常的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
Java四舍五入時(shí)保留指定小數(shù)位數(shù)的五種方式
這篇文章主要介紹了Java四舍五入時(shí)保留指定小數(shù)位數(shù)的五種方式,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-09-09
Kotlin基礎(chǔ)教程之控制流(順序,分支,循環(huán))
這篇文章主要介紹了Kotlin基礎(chǔ)教程之控制流的相關(guān)資料,需要的朋友可以參考下2017-05-05
SpringCloud Feign 服務(wù)調(diào)用的實(shí)現(xiàn)
Feign是一個(gè)聲明性web服務(wù)客戶端。本文記錄多個(gè)服務(wù)之間使用Feign調(diào)用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01

