Java設計模式(一)之建立型模式:工廠模式(簡單工廠模式+工廠方法模式)
在面向物件程式設計中, 最通常的方法是一個new操作符產生一個物件例項,new操作符就是用來構造物件例項的。但是在一些情況下, new操作符直接生成物件會帶來一些問題。舉例來說,許多型別物件的建立需要一系列的步驟:你可能需要計算或取得物件的初始位置;選擇生成哪個子物件例項;或在你生成你需要的物件之前必須先生成一些輔助功能的物件。 在這些情況,新物件的建立就是一個 “過程”,不僅是一個操作,像一部大機器中的一個齒輪傳動。
模式的問題:你如何能輕鬆方便地構造物件例項,而不必關心構造物件示例的細節和複雜過程?
解決方案:建立一個工廠類建立物件。
一、分類:
工廠模式主要是為建立物件提供過渡介面,以便將建立物件的具體過程遮蔽隔離起來,達到提高靈活性的目的。
工廠模式可以分為三類:
(1)簡單工廠模式
(2)工廠方法模式
(3)抽象工廠模式
這三種模式從上到下逐步抽象,並且更具一般性。GOF在《設計模式》一書中將工廠模式分為兩類:工廠方法模式(Factory Method)與抽象工廠模式(Abstract Factory)。將簡單工廠模式(Simple Factory)看為工廠方法模式的一種特例,兩者歸為一類。
二、介紹:
1、還沒有工廠時代:假如還沒有工業革命,如果一個客戶要一款寶馬車,一般的做法是客戶去建立一款寶馬車,然後拿來用。
2、簡單工廠模式:後來出現工業革命。使用者不用去建立寶馬車。因為客戶有一個工廠來幫他建立寶馬.想要什麼車,這個工廠就可以建。比如想要320i系列車。工廠就建立這個系列的車。即工廠可以建立產品。
3、工廠方法模式時代:為了滿足客戶,寶馬車系列越來越多,如320i,523i,30li等系列,一個工廠無法建立所有的寶馬系列。於是由單獨分出來多個具體的工廠。每個具體工廠建立一種系列。即具體工廠類只能建立一個具體產品。但是寶馬工廠還是個抽象。你需要指定某個具體的工廠才能生產車出來。
4、抽象工廠模式時代:隨著客戶的要求越來越高,寶馬車必須配置空調。於是這個工廠開始生產寶馬車和需要的空調。
最終是客戶只要對寶馬的銷售員說:我要523i空調車,銷售員就直接給他523i空調車了。而不用自己去建立523i空調車寶馬車。
這就是工廠模式。
三、區別:
1、工廠方法模式:
只有一個抽象產品類,可以派生出多個具體產品類;
一個抽象工廠類,可以派生出多個具體工廠類;
每個具體工廠類只能建立一個具體產品類的例項。
2、抽象工廠模式:
擁有多個抽象產品類(產品族),每個抽象產品類可以派生出多個具體產品類;
一個抽象工廠類,可以派生出多個具體工廠類;
每個具體工廠類可以建立多個具體產品類的例項。
3、區別:
工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個。
工廠方法模式的具體工廠類只能建立一個具體產品類的例項,而抽象工廠模式可以建立多個。
四、簡單工廠模式:
1、分步說明引子:從無到有。如果不使用工廠,客戶將自己建立寶馬車,然後拿來用。
public class BMW320 {
public BMW320(){
System.out.println("製造-->BMW320");
}
}
public class BMW523 {
public BMW523(){
System.out.println("製造-->BMW523");
}
}
public class Customer {
public static void main(String[] args) {
BMW320 bmw320 = new BMW320();
BMW523 bmw523 = new BMW523();
}
}
客戶需要知道怎麼去建立一款車,客戶和車就緊密耦合在一起了.為了降低耦合,就出現了工廠類,把建立寶馬的操作細節都放到了工廠裡面去,客戶直接使用工廠的建立工廠方法,傳入想要的寶馬車型號就行了,而不必去知道建立的細節.這就是工業革命了:簡單工廠模式。
2、簡單工廠模式:我們建立一個工廠類方法來製造新的物件。如圖:
產品類:
abstract class BMW {
public BMW(){
}
}
public class BMW320 extends BMW {
public BMW320() {
System.out.println("製造-->BMW320");
}
}
public class BMW523 extends BMW{
public BMW523(){
System.out.println("製造-->BMW523");
}
}
工廠類:
public class Factory {
public BMW createBMW(int type) {
switch (type) {
case 320:
return new BMW320();
case 523:
return new BMW523();
default:
break;
}
return null;
}
}
客戶類:
public class Customer {
public static void main(String[] args) {
Factory factory = new Factory();
BMW bmw320 = factory.createBMW(320);
BMW bmw523 = factory.createBMW(523);
}
}
簡單工廠模式存在的目的很簡單,即定義一個用於建立物件的介面。將物件的建立和物件本身的業務處理分離了,可以降低系統的耦合度,使得兩者修改起來相對容易些,當以後實現改變時,只需要修改工廠類即可。
3、組成:
(1)工廠類角色: 這是本模式的核心,含有一定的商業邏輯和判斷邏輯,用來建立產品
(2)抽象產品角色:它一般是具體產品繼承的父類或者實現的介面。
(3)具體產品角色:工廠類所建立的物件就是此角色的例項。在java中由一個具體類實現。
4、優點:
(1)簡單工廠模式實現了對責任的分割,提供了專門的工廠類用於建立物件,實現物件的建立和物件的使用分離。
(2)客戶端無須知道所建立的具體產品類的類名,只需要知道具體產品類所對應的引數即可,對於一些複雜的類名,通過簡單工廠模式可以減少使用者的記憶量。
(3)通過引入配置檔案,可以在不修改任何客戶端程式碼的情況下更換和增加新的具體產品類,在一定程度上提高了系統的靈活性。
5、缺點:
(1)由於工廠類集中了所有產品建立邏輯,一旦不能正常工作,整個系統都要受到影響。
(2)對產品部分來說,它是符合開閉原則的,但是工廠部分不符合,系統擴充套件困難,一旦新增新產品就不得不修改工廠邏輯,在產品型別較多時,有可能造成工廠邏輯過於複雜,不利於系統的擴充套件和維護。
6、使用場景:
(1)工廠類負責建立的對昂比較少;
(2)客戶端只知道傳入工廠類的引數,對於如何建立物件不關心。
為了解決簡單工廠模式的問題,於是工廠方法模式出現了。工廠類定義成了介面,而每新增的車種型別,就增加該車種型別對應工廠類的實現,這樣工廠的設計就可以擴充套件了,而不必去修改原來的程式碼。
五、工廠方法模式:
工廠方法模式定義了一個建立物件的介面,但由子類決定要例項化的類是哪一個。工廠方法模式讓例項化推遲到子類。並使用繼承自抽象工廠角色的多個子類來代替簡單工廠模式中的工廠類。分擔了物件承受的壓力;而且這樣使得結構變得靈活起來——當有新的產品產生時,只要按照抽象產品角色、抽象工廠角色提供的介面來生成,那麼就可以被客戶使用,而不必去修改任何已有的程式碼。可以看出工廠角色的結構也是符合開閉原則的!
1、工廠方法模式組成:
(1)抽象工廠角色: 這是工廠方法模式的核心,它與應用程式無關。是具體工廠角色必須實現的介面或者必須繼承的父類。在java中它由抽象類或者介面來實現。
(2)具體工廠角色:它含有和具體業務邏輯有關的程式碼。由應用程式呼叫以建立對應的具體產品的物件。
(3)抽象產品角色:它是具體產品繼承的父類或者是實現的介面。在java中一般有抽象類或者介面來實現。
(4)具體產品角色:具體工廠角色所建立的物件就是此角色的例項。在java中由具體的類來實現。
2、程式碼如下:
產品類:
abstract class BMW {
public BMW(){
}
}
public class BMW320 extends BMW {
public BMW320() {
System.out.println("製造-->BMW320");
}
}
public class BMW523 extends BMW{
public BMW523(){
System.out.println("製造-->BMW523");
}
}
工廠類:
interface FactoryBMW {
BMW createBMW();
}
public class FactoryBMW320 implements FactoryBMW{
@Override
public BMW320 createBMW() {
return new BMW320();
}
}
public class FactoryBMW523 implements FactoryBMW {
@Override
public BMW523 createBMW() {
return new BMW523();
}
}
客戶類:
public class Customer {
public static void main(String[] args) {
FactoryBMW320 factoryBMW320 = new FactoryBMW320();
BMW320 bmw320 = factoryBMW320.createBMW();
FactoryBMW523 factoryBMW523 = new FactoryBMW523();
BMW523 bmw523 = factoryBMW523.createBMW();
}
}
3、優點:
(1) 在工廠方法中,使用者只需要知道所要產品的具體工廠,無須關係具體的建立過程,甚至不需要具體產品類的類名。
(2)在系統增加新的產品時,我們只需要新增一個具體產品類和對應的實現工廠,無需對原工廠進行任何修改,很好地符合了“開閉原則”。
4、缺點:
(1)每次增加一個產品時,都需要增加一個具體類和物件實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。這並不是什麼好事。
5、小結:
(1)工廠方法模式完全符合“開閉原則”。
(2)工廠方法模式使用繼承,通過子類實現工廠方法來建立物件。將物件的建立和例項化委託給子類。在這裡我們要明白這並不是工廠來決定生成哪種產品,而是在編寫抽象工廠類時,不需要知道實際建立的產品是哪個;但是當選擇了使用哪個子類,就已經決定了實際建立的產品時哪個了。
參考文章:
https://blog.csdn.net/jason0539/article/details/23020989
https://blog.csdn.net/chenssy/article/details/8964657
https://blog.csdn.net/chenssy/article/details/8974868