工廠模式詳解
簡述
工廠模式是Java最常用的設計模式之一,這種模式屬於建立型模式,提供了一種建立物件的最佳模式。它並不是一個獨立的設計模式,而是三種功能接近的設計模式的統稱,分別是簡單工廠模式,工廠方法模式,抽象工廠模式。
案例引入
當我們例項化一個物件的時候,一般我們直接使用new關鍵字,但我們有沒有想到如果建立物件需要一系列複雜的初始化過程,我們就要在物件的建構函式寫很長很長的程式碼,大大降低了程式的可讀性,同時也可能導致程式的耦合度較高,這裡就可以提到我們的工廠模式了。
簡單工廠模式
我們在例項化物件的時候,不使用new關鍵字,而是交由一個新的類,叫工廠類建立。
我們來看一個例子,在我們的業務程式碼中,有個被廣泛引用的“口罩”類,這裡類例項需要在許多地方被建立和初始化,且初始化的程式碼較為複雜。
publicclassMask{ //建構函式 publicMask(){ //..... //100行初始化程式碼 } }
此時我們就可以新建一個口罩工廠類,用於例項化口罩類,把初始化程式碼搬進工廠裡面。
publicclassMaskFactory{ publicMaskcreateMask(){ Maskmask=newMask(); //..... //100行初始化程式碼 returnmask; } }
如果口罩類存在子類,可以是繼承,可以是介面
我們就根據輸入的引數來決定生產出哪種產品
像這樣通過工廠類建立物件,且根據傳入的引數決定具體子類物件的做法,就是簡單工廠模式。
工廠方法模式
但若我們需要新加新的口罩子類,口罩工廠的建立方法中就需要新增新的if-else判斷,這樣就不符合面向物件的開放-封閉原則。
所謂面向物件的開放-封閉原則,就是在程式中對“擴充套件”開放,對“修改”封閉。如果每次業務改動都要增加新的if-else,就涉及對舊有程式碼的修改,不但容易出錯,可讀性也不好。
想要解決這個問題,我們可以為每個口罩子類建立對應的工廠子類,這些工廠子類分別實現抽象的工廠介面。這樣一來,我們只需例項化不同的工廠子類,呼叫建立方法,得到的就是對應的口罩物件,這背後是面向物件的多型特性。
根據這個思路,我們重構一下工廠,現在工廠是個介面,抽象方法是createMask。
然後工廠有兩個子類——高階口罩工廠和低埠罩工廠
他們實現了createMask方法
在程式碼中,工廠類變成了抽象的介面,高階口罩工廠和低埠罩工廠這兩個子類分別實現了這兩個介面。
在客戶端,想要建立什麼口罩物件,只需要例項化不同的工廠子類,然後呼叫他們的建立方法即可,無需再傳入引數。
像這樣每一個口罩子類都對應一個工廠子類,利用多型性質動態建立物件的模式,就是工廠方法模式。
抽象工廠模式
如果業務中我們要建立口罩,防毒面具,防護服三種產品,且每一種產品都包含高階到低端兩類,如果按照工廠方法模式建立工廠子類,就如下圖所示:
當產品數量很多的時候,工廠類的數量也會越來越多,搞得非常複雜。
那該怎麼辦呢——我們不需要為每一個產品配置一個工廠,而是可以把這些產品進行分組。對於上面的例子我們可以分成高階組和低端組,由同一個工廠類的不同方法建立。
我們以口罩和防護服舉例,他們是兩個介面,分別由高階和低端兩個實現類:
publicinterfaceIMask{ voidshowMask(); } publicclassLowEndMaskimplementsIMask{ @Override publicvoidshowMask(){ System.out.println("我的低埠罩"); } } publicclassHighEndMaskimplementsIMask{ @Override publicvoidshowMask(){ System.out.println("我是高階口罩"); } } publicinterfaceIProtectiveSuit{ voidshowSuit(); } publicclassLowEndProtectiveSuitimplementsIProtectiveSuit{ @Override publicvoidshowSuit(){ System.out.println("我是低端防護服"); } } publicclassHighEndProtectiveSuitimplementsIProtectiveSuit{ @Override publicvoidshowSuit(){ System.out.println("我是高階防護服"); } }
然後是工廠類,因為產品分成了高階和低端兩個組,工廠也就分成了高階工廠和低端工廠,各自負責組內產品的建立:
publicinterfaceIFactory{ //建立口罩 IMaskcreateMask(); //建立防護服 IProtectiveSuitcreateSuit(); } publicclassLowEndFactoryimplementsIFactory{ @Override publicIMaskcreateMask(){ IMaskmask=newLowEndMask(); //..... //LowEndMask的100行初始化程式碼 returnmask; } @Override publicIProtectiveSuitcreateSuit(){ IProtectiveSuitsuit=newLowEndProtectiveSuit(); //..... //LowEndProtectiveSuit的100行初始化程式碼 returnsuit; } } publicclassHighEndFactoryimplementsIFactory{ @Override publicIMaskcreateMask(){ IMaskmask=newHighEndMask(); //..... //HighEndMask的100行初始化程式碼 returnmask; } @Override publicIProtectiveSuitcreateSuit(){ IProtectiveSuitsuit=newHighEndProtectiveSuit(); //..... //HighEndProtectiveSuit的100行初始化程式碼 returnsuit; } }
然後我們寫test類,通過例項化不同工廠子類,呼叫不同建立方法,就可以創建出不同的產品:
像這樣把產品分組,組內不同的產品對應同一工廠的不同方法的設計模式,就叫做抽象工廠模式。
總結
•簡單工廠模式有唯一的工廠類,工廠類的建立方法根據傳入的引數做if-else條件判斷,決定最終建立什麼樣的產品物件。
•工廠方法模式由多個工廠類實現工廠介面,利用多型來建立不同的產品物件,從而避免了冗長的if-else條件判斷。
•抽象工廠模式把產品子類進行分組,同組中的不同產品由同一個工廠子類的不同方法負責建立,從而減少了工廠子類的數量。
reference
程式設計師小灰:https://blog.csdn.net/bjweimengshu/article/details/108591085
https://blog.csdn.net/bjweimengshu/article/details/108459337