第一次看到這個名詞是在Effective的第一條中,書中先是數落了一番構造器之后提出靜態工廠方法的好處如何如何。看完后覺得,雖然這個名詞之前沒聽過,其實在開發途中用的不少,入類型轉換valueOf(),單例模式中的getInstance()均有靜態工廠模式的痕跡。首先是不太認可書中所說的好處,於是上網尋找資料。總結如下:
一、什么是靜態工廠方法
其又叫簡單工廠模式,與工廠模式不同,其是通過專門定義一個類來負責創建其他類的實例,其實例通常擁有共同父類,其普遍實現主要依靠Java的反射機制。
二、好處怎么體現
Effective Java中共提到好處四點:
1、它們有名稱
2、它們可以返回原返回類型任意子類型的對象。
針對於第一點,相比較於與類名相同的構造函數,靜態工廠方法是通過靜態方法進行對象的初始化,其方法名字自然可以自定義,從而幫助開發人員的理解,這是容易理解的。例如,重載而來的構造函數,很難在不看源碼的情況下知道他們的區別。
第二點,其在Java中的集合類Collections用的頗多,主要利用Java的多態的特性,使得工廠可以產生基類的同時注入子類實現。
如:
1 public interface Food { 2 3 /** 4 * 使得所有食物都有一個共有的introduce方法 5 */ 6 public void introduce(); 7 }
1 /** 2 * 定義食物的子類:魚 3 */ 4 public class Fish implements Food{ 5 6 @Override 7 public void introduce() { 8 System.out.println("i am a fish"); 9 } 10 }
1 /** 2 * 食物的子類,水果 3 */ 4 public class Fruit implements Food { 5 @Override 6 public void introduce() { 7 System.out.println("i am the fruit"); 8 } 9 }
1 /** 2 * 通過反射機制實現的工廠 3 */ 4 public class FoodFactory { 5 6 public static Food getFood(String type) { 7 Food food = null; 8 try { 9 food = (Food) Class.forName("info.zhw." + type).newInstance(); 10 } catch (ClassNotFoundException e) { 11 e.printStackTrace(); 12 } catch (InstantiationException e) { 13 e.printStackTrace(); 14 } catch (IllegalAccessException e) { 15 e.printStackTrace(); 16 } 17 return food; 18 } 19 }
FoodFactory就利用了基類,返回了該類型的子類型。
3、不必在每次調用他們的時候都創建一次對象。
使用構造函數,調用其中的方法,則實例化一個類是必不可少的步奏,而是使用靜態工廠方法,則可以對對象進行重復利用,這個特點在單例模式中使用頗多。
public class SingletonClass{ private static SingletonClass instance=null; public static SingletonClass getInstance() { if(instance==null) { synchronized(SingletonClass.class) { if(instance==null) instance=new SingletonClass(); } } return instance; } private SingletonClass(){ } }
其將構造方法私有,只能通過getInstance()獲取實例,從而達到實例重復利用的目的。
4、使代碼簡潔
與第一點有點雷同,主要也是在方便理解的基礎上作出的改進。
三、缺點從何體現
1、如果類不含有公有或受保護構造器,就不能被子類化。
2、和靜態方法實際上沒有任何區別。其無法在API文檔中明確標出,推薦使用管用名稱管理。
以上是Effective Java中提到的缺點,不疼不癢的樣子,也許是我理解不深入的緣故。
3、網上摘錄的一段(http://blog.163.com/zhuowh2006@126/blog/static/10182372420133220511247/)
由於工廠類集中了所有實例的創建邏輯,這就直接導致一旦這個工廠出了問題,所有的客戶端都會受到牽連;而且由於簡單工廠模式的產品室基於一個共同的抽象類或者接口,這樣一來,但產品的種類增加的時候,即有不同的產品接口或者抽象類的時候,工廠類就需要判斷何時創建何種種類的產品,這就和創建何種種類產品的產品相互混淆在了一起,違背了單一職責,導致系統喪失靈活性和可維護性。而且更重要的是,簡單工廠模式違背了“開放封閉原則”,就是違背了“系統對擴展開放,對修改關閉”的原則,因為當我新增加一個產品的時候必須修改工廠類,相應的工廠類就需要重新編譯一遍。
四、總結
廢話一句,需要根據實際情況選擇合適的解決方案,實現時多了一種考慮,在使用構造器之前,考慮下靜態工廠方法吧。