抽象工廠模式中咱們能夠定義實現不止一個接口,一個工廠也能夠生成不止一個產品類,抽象工廠模式較好的實現了「開放-封閉」原則,是三個模式中較爲抽象,並具通常性的模式。咱們在使用中要注意使用抽象工廠模式的條件。
以前寫過一篇關於工廠模式(Factory Pattern)的隨筆,裏面分析了簡單工廠模式,但對於工廠方法和抽象工廠的分析較爲簡略。這裏從新分析分析三者的區別,工廠模式是java設計模式中比較簡單的一個設計模式,但不少地方都用到了工廠模式,(如解析xml中,jdbc鏈接數據庫等)利用好工廠模式對程序的設計頗有用處。工廠模式在一些設計模式的書中分爲簡單工廠模式,工廠方法模式和抽象工廠模式三類。也有把工廠方法模式劃分到抽象工廠模式的,認爲工廠方法是抽象工廠模式的特例的一種,就是隻有一個要實現的產品接口。下面結合例子分析三者的區別。java
首先是簡單工廠模式,這裏以工廠生產產品爲例。數據庫
產品類的共同接口設計模式
1 1 package factory; 2 2 /** 3 3 * 4 4 * @author CIACs 5 5 * 6 6 */ 7 7 public interface Product { 8 8 //聲明類所需繼承的共同接口,也能夠是抽象類 9 9 }
產品Aide
1 package factory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class ProductA implements Product { 8 public ProductA() { 9 System.out.println("ProductA"); 10 } 11 }
產品Bpost
1 package factory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class ProductB implements Product { 8 public ProductB() { 9 System.out.println("ProductB"); 10 } 11 }
工廠類spa
1 package factory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Factory { 8 //能夠在工廠類中添加任何你所須要的邏輯 9 public static Product create(String str) 10 { 11 //生成ProductA 12 if(str.equalsIgnoreCase("ProductA")) 13 { 14 return new ProductA(); 15 } 16 else 17 //生成ProductB 18 if(str.equalsIgnoreCase("ProductB")) 19 { 20 return new ProductB(); 21 } 22 return null; 23 } 24 25 }
客戶端設計
1 package factory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Client { 8 public static void main(String[] args) { 9 //調用Factory的靜態方法生成所要的類 10 Factory.create("productA"); 11 Factory.create("ProductB"); 12 } 13 }
控制檯輸出結果:3d
簡單工廠模式實現了生成產品類的代碼跟客戶端代碼分離,在工廠類中你能夠添加所需的生成產品的邏輯代碼,可是問題來了,優秀的java代碼是符合「開放-封閉」原則的,也就是說對擴展開發,對修改關閉,若是你要加一個產品類C,你就要修改工廠類裏面的生成產品的代碼,在這裏你就要增長if-else判斷。對於這個問題,咱們的工廠方法模式就能夠解決這個問題。code
接下來是工廠方法模式xml
產品類中增長了ProductC(其餘產品類的代碼是能夠重用上面的,只要把包名更改了就行)。
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 8 public class ProductC implements Product { 9 public ProductC() { 10 System.out.println("productC"); 11 } 12 }
聲明工廠接口
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public interface Factory { 8 //聲明產生產品類的方法 9 public Product createProduct(); 10 }
產生ProductA的FactoryA
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class FactoryA implements Factory { 8 //實現工廠類的方法生成產品類A 9 public Product createProduct() 10 { 11 return new ProductA(); 12 } 13 14 }
產生ProductB的FactoryB
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class FactoryB implements Factory { 8 //實現工廠類的方法生成產品類B 9 public Product createProduct() 10 { 11 return new ProductB(); 12 } 13 }
產生ProductC的FactoryC
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class FactoryC implements Factory { 8 //實現工廠類的方法生成產品類C 9 public Product createProduct() 10 { 11 return new ProductC(); 12 } 13 }
客戶端
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Client { 8 public static void main(String[] args) { 9 Factory factory; 10 factory = new FactoryA(); 11 factory.createProduct(); 12 factory = new FactoryB(); 13 factory.createProduct(); 14 factory = new FactoryC(); 15 factory.createProduct(); 16 } 17 }
控制檯輸出結果:
工廠方法模式中咱們把生成產品類的時間延遲,就是經過對應的工廠類來生成對應的產品類,在這裏咱們就能夠實現「開發-封閉」原則,不管加多少產品類,咱們都不用修改原來類中的代碼,而是經過增長工廠類來實現。可是這仍是有缺點的,若是產品類過多,咱們就要生成不少的工廠類。假如咱們要實現的產品接口不止一個,也就是有多個產品接口,不一樣產品接口有對應的產品族。什麼是產品族呢?簡單的理解就是,不一樣牌子產的車裏面會有跑車類型,家庭類型,商用類型等的車,不一樣牌子的車的跑車類型的車能夠組成一個產品族。對於這種狀況咱們能夠採用抽象工廠模式。
最後是抽象工廠模式,在這裏咱們爲不一樣產品附加上對應的禮物,就是說ProductA中會有GiftA。
增長的Gift接口
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public interface Gift { 8 //聲明產品贈品的接口,固然也能夠是抽象類,一樣爲了簡單就不聲明方法了 9 }
GiftA類
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class GiftA implements Gift { 8 public GiftA() 9 { 10 System.out.println("GiftA"); 11 } 12 }
GiftB類
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class GiftB implements Gift { 8 public GiftB() 9 { 10 System.out.println("GiftB"); 11 } 12 }
Factory接口
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 *聲明Product類工廠和Gift類工廠的工同工廠接口 6 */ 7 public interface Factory { 8 public Product createProduct(); 9 public Gift createGift(); 10 11 }
生成ProductA和GiftA的FactoryA
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 *FactoryA能夠生成ProductA和GiftA 6 */ 7 public class FactoryA implements Factory { 8 @Override 9 public Product createProduct() 10 { 11 return new ProductA(); 12 } 13 @Override 14 public Gift createGift() 15 { 16 return new GiftA(); 17 } 18 }
生成ProductB和GiftB的FactoryB
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 *FactoryB能夠生成ProductB和GiftB 6 */ 7 public class FactoryB implements Factory { 8 @Override 9 public Product createProduct() { 10 return new ProductB(); 11 } 12 @Override 13 public Gift createGift() { 14 return new GiftB(); 15 } 16 17 }
客戶端
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Client { 8 public static void main(String[] args) { 9 Factory factory; 10 factory = new FactoryA(); 11 factory.createProduct(); 12 factory.createGift(); 13 factory = new FactoryB(); 14 factory.createProduct(); 15 factory.createGift(); 16 } 17 }
控制檯輸出結果:
抽象工廠模式中咱們能夠定義實現不止一個接口,一個工廠也能夠生成不止一個產品類,抽象工廠模式較好的實現了「開放-封閉」原則,是三個模式中較爲抽象,並具通常性的模式。咱們在使用中要注意使用抽象工廠模式的條件。