Java設計模式——工廠設計模式


工廠模式:主要用來實例化有共同接口的類,工廠模式可以動態決定應該實例化那一個類。
工廠模式的形態
工廠模式主要用一下幾種形態:
1:簡單工廠(Simple Factory)。
2:工廠方法(Factory Method)。
3:抽象工廠(Abstract Factory)。

簡單工廠(Simple Factory)
又叫 靜態工廠,是工廠模式三中狀態中結構最為簡單的。主要有一個靜態方法,用來接受參數,並根據參數來決定返回實現同一接口的不同類的實例。我們來看一個具體的例子:
假設一家工廠,幾生產洗衣機,有生產冰箱,還有空調等等..
我們先為所有產品定義一個共同的產品接口
Java代碼 復制代碼 收藏代碼
  1. public interface Product{} 

接着我們讓這個工廠的所有產品都必須實現此接口
Java代碼 復制代碼 收藏代碼
  1. public class Washer implements Product{ 
  2.    public Washer(){ 
  3.        System.out.println("洗衣機被制造了"); 
  4.    } 
  5.  
  6. public class Icebox implements Product{ 
  7.    public Icebox(){ 
  8.        System.out.println("冰箱被制造了"); 
  9.    } 
  10.  
  11. public class AirCondition implements Product{ 
  12.    public Icebox(){ 
  13.        System.out.println("空調被制造了"); 
  14.    } 

接下來我們來寫一個工廠類,有它來負責生產以上的產品
Java代碼 復制代碼 收藏代碼
  1. public class SimpleFactory { 
  2.      
  3.     public static Product factory(String productName) throws Exception{ 
  4.         if(productName.equals("Washer")){ 
  5.             return new Washer(); 
  6.         }else if(productName.equals("Icebox")){ 
  7.             return new Icebox(); 
  8.         }else if(productName.equals("AirCondition")){ 
  9.             return new AirCondition(); 
  10.         }else
  11.             throw new Exception("沒有該產品"); 
  12.         } 
  13.     } 

好了,有了這個工廠類,我們就可以開始下定單了, SimpleFactory將根據不同的定單類決定生產什么產品。
Java代碼 復制代碼 收藏代碼
  1. public static void main(String[] args) { 
  2.     try
  3.               SimpleFactory.factory("Washer"); 
  4.               SimpleFactory.factory("Icebox"); 
  5.               SimpleFactory.factory("AirCondition"); 
  6.             } catch (Exception e) { 
  7.         e.printStackTrace(); 
  8.     } 

由上面的代碼可以看出,簡單工廠的核心就是一個 SimpleFactory類,他擁有必要的邏輯判斷能力和所有產品的創建權利,我們只需要向把定單給他,就能得到我們想要的產品。這使用起來似乎非常方便。
但,實際上,這個 SimpleFactory有很多的局限。首先,我們每次想要增加一種新產品的時候,都必須修改 SimpleFactory的原代碼。其次,當我們擁有很多很多產品的時候,而且產品之間又存在復雜的層次關系的時候,這個類必須擁有復雜的邏輯判斷能力,其代碼量也將不斷地激增,這對以后的維護簡直就是恐怖兩個字...
還有就是,整個系統都嚴重依賴 SimpleFactory類,只要 SimpleFactory類一出問題,系統就進入不能工作的狀態,這也是最為致命的一點....
以上的不足將在工廠模式的另外兩種狀態中得到解決。

工廠方法(Factory Method)
上面的代碼告訴我們, 簡單工廠並不簡單,它是整個模式的核心,一旦他出了問題,整個模式都將受影響而不能工作,為了降低風險和為日后的維護、擴展做准備,我們需要對它進行重構,引入 工廠方法
工廠方法為工廠類定義了接口,用多態來削弱了工廠類的職能,以下是工廠接口的定義:
Java代碼 復制代碼 收藏代碼
  1. public interface Factory{ 
  2.   public Product create(); 

我們再來定義一個產品接口
Java代碼 復制代碼 收藏代碼
  1. public interface Product{} 

一下是實現了產品接口的產品類
Java代碼 復制代碼 收藏代碼
  1. public class Washer implements Product{ 
  2.    public Washer(){ 
  3.        System.out.println("洗衣機被制造了"); 
  4.    } 
  5.  
  6. public class Icebox implements Product{ 
  7.    public Icebox(){ 
  8.        System.out.println("冰箱被制造了"); 
  9.    } 
  10.  
  11. public class AirCondition implements Product{ 
  12.    public Icebox(){ 
  13.        System.out.println("空調被制造了"); 
  14.    } 

接下來,就是工廠方法的核心部分,也就是具體創建產品對象的具體工廠類,
Java代碼 復制代碼 收藏代碼
  1. //創建洗衣機的工廠 
  2. public class CreateWasher implements Factory{ 
  3.     public Product create(){ 
  4.           return new Washer(); 
  5.     } 
  6.  
  7. //創建冰箱的工廠 
  8. public class CreateIcebox implements Factory{ 
  9.     public Product create(){ 
  10.           return new Icebox(); 
  11.     } 
  12.  
  13. //創建空調的工廠 
  14. public class CreateAirCondition implements Factory{ 
  15.     public Product create(){ 
  16.           return new AirCondition(); 
  17.     } 

從上面創建產品對象的代碼可以看出, 工廠方法簡單工廠的主要區別是, 簡單工廠是把創建產品的職能都放在一個類里面,而 工廠方法則把不同的產品放在實現了工廠接口的不同工廠類里面,這樣就算其中一個工廠類出了問題,其他工廠類也能正常工作,互相不受影響,以后增加新產品,也只需要新增一個實現工廠接口工廠類,就能達到,不用修改已有的代碼。但 工廠方法也有他局限的地方,那就是當面對的產品有復雜的等級結構的時候,例如,工廠除了生產家電外產品,還生產手機產品,這樣一來家電是手機就是兩大產品家族了,這兩大家族下面包含了數量眾多的產品,每個產品又有多個型號,這樣就形成了一個復雜的產品樹了。如果用 工廠方法來設計這個產品家族系統,就必須為每個型號的產品創建一個對應的工廠類,當有數百種甚至上千種產品的時候,也必須要有對應的上百成千個工廠類,這就出現了傳說的類爆炸,對於以后的維護來說,簡直就是一場災難.....

抽象工廠(Factory Method)
抽象工廠:意的意圖在於創建一系列互相關聯或互相依賴的對象。<<Java設計模式>>
我自己覺得 抽象工廠是在 工廠方法的基礎上引進了分類管理的概念....
工廠方法用來創建一個產品,它沒有分類的概念,而抽象工廠則用於創建一系列產品,所以產品分類成了抽象工廠的重點,
我們繼續用上面的例子來說明:
工廠生產的所有產品都用都用大寫字母來標明它們的型號,比如冰箱,就有“冰箱-A",“冰箱-B",同樣,其他的產品也都是遵守這個編號規則,於是就有了一下產品家族樹

冰箱:

      
  1. 冰箱-A
  2.   
  3. 冰箱-B


洗衣機:

      
  1. 洗衣機-A
  2.   
  3. 洗衣機-B

我們可以為冰箱和洗衣機分別定義兩個產品接口,以對他們進行分類,
Java代碼 復制代碼 收藏代碼
  1. //洗衣機接口 
  2. public interface Washer{ 
  3.  
  4. //冰箱接口 
  5. public interface Icebox{ 

接着,我們分別創建這兩個接口的具體產品
Java代碼 復制代碼 收藏代碼
  1. //洗衣機-A 
  2. public class WasherA implements Washer{ 
  3.    public WasherA(){ 
  4.        System.out.println("洗衣機-A被制造了"); 
  5.    } 
  6.  
  7. //洗衣機-B 
  8. public class WasherB implements Washer{ 
  9.    public WasherB(){ 
  10.        System.out.println("洗衣機-B被制造了"); 
  11.    } 
  12.  
  13. //冰箱-A 
  14. public class IceboxA implements Icebox{ 
  15.    public IceboxA(){ 
  16.        System.out.println("冰箱-A被制造了"); 
  17.    } 
  18.  
  19. //冰箱-B 
  20. public class IceboxB implements Icebox{ 
  21.    public IceboxB(){ 
  22.        System.out.println("冰箱-B被制造了"); 
  23.    } 

到此,產品部分我們准備好了,接下來我們來處理工廠部分,我們先來定義工廠行為接口
Java代碼 復制代碼 收藏代碼
  1. public interface Factory{ 
  2.        public Washer createWasher(); 
  3.        public Icebox createIcebox(); 

接下來我創造具體的工廠類,我們根據上面產品的接口,把型號A的產品分為一類,由一個工廠來管理,把型號為B的產品有另一個工廠管理,根據這個分類,我們可以實現如下的兩個具體工廠類
Java代碼 復制代碼 收藏代碼
  1. //創建型號為A的產品工廠 
  2. public class FactoryA implements Factory{ 
  3.        //創建洗衣機-A 
  4.        public Washer createWasher(){ 
  5.             return new WasherA(); 
  6.        } 
  7.  
  8.        //創建冰箱-A 
  9.        public Icebox createIcebox(){ 
  10.             return new IceboxA(); 
  11.        } 
  12.  
  13. //創建型號為B的產品工廠 
  14. public class FactoryB implements Factory{ 
  15.        //創建洗衣機-B 
  16.        public Washer createWasher(){ 
  17.             return new WasherB(); 
  18.        } 
  19.  
  20.        //創建冰箱-B 
  21.        public Icebox createIcebox(){ 
  22.             return new IceboxB(); 
  23.        } 


這樣,我們的抽象工廠就完成了。有上面可以看出,在運用上我覺得工廠方法和抽象工廠,都有自己的應用場景,並沒有什么優劣之分,但在應用抽象工廠之前,要先對創建的對象進行系統的分類,這點很重要,好的產品分類規則能為具體工廠類的選擇調用和以后的擴展提供清晰的思路.

 

注: 本文引用自:http://chjl2020.iteye.com/blog/265283


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM