工廠模式(Factory Pattern)是 Java 中最經常使用的設計模式之一。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。html
在工廠模式中,咱們在建立對象時不會對客戶端暴露建立邏輯,而且是經過使用一個共同的接口來指向新建立的對象。java
工廠模式主要分爲三種形式設計模式
簡單工廠模式(不屬於GoF的23種設計模式中)ide
工廠方法模式函數
抽象工廠模式ui
簡單來講,本質上工廠模式是對建立對象過程的一種封裝。經過封裝,讓客戶端無需在乎對象建立的過程和邏輯。看看下面的例子。操作系統
本文部分解釋摘錄自 http://c.biancheng.net/view/1351.html.net
好比咱們去一家餐廳。咱們想要點餐吃飯。設計
那麼能夠看做是客戶獲得了飲料,食物,餐具,而後一一使用。咱們先如下單食物爲例,寫個例子。code
不使用工廠模式時是這樣的
public static void main(String[] args) { // 普通建立對象 Hamburger hamburger = new Hamburger(); Steak steak = new Steak(); hamburger.eat(); steak.eat(); }
然而這樣的建立對象,語義上不清晰且須要在客戶端中初始化對象。
畢竟給咱們製做食物的是餐廳,因此咱們能夠把餐廳理解成一種工廠。咱們客戶向餐廳點單就好了。
首先,餐廳生產的食品Food,均可以食用,建立接口eat。
public interface Food { void eat(); }
那麼使用漢堡和牛扒就應該以下實現
public class Hamburger implements Food { @Override public void eat() { System.out.println("吃漢堡,嘎嘎嘎"); } } public class Steak implements Food { @Override public void eat() { System.out.println("吃牛扒,嘎嘎嘎"); } }
那麼餐廳,就能夠做爲生產這些產品的工廠
public class RestaurantFactory { public Food getFood(String type) { if (type == null) return null; else if (type.equalsIgnoreCase("hamburger")) return new Hamburger(); else if (type.equalsIgnoreCase("steak")) return new Steak(); return null; } }
有了餐廳工廠之後,客戶下單就不須要本身去new食物了。直接問餐廳拿!
public static void main(String[] args) { // 普通建立對象 Hamburger hamburger = new Hamburger(); Steak steak = new Steak(); hamburger.eat(); steak.eat(); // 利用簡單工廠建立對象 RestaurantFactory rpf = new RestaurantFactory(); Food hamburger = rpf.getFood("hamburger"); Food steak = rpf.getFood("steak"); hamburger.eat(); steak.eat(); }
上面是普通建立,下面是簡單工廠建立,最後會輸出2次
吃漢堡,嘎嘎嘎
吃牛排,嘎嘎嘎
上面咱們能夠看到,咱們把建立對象都寫進了一個方法裏。其實咱們也能夠分開寫,一個方法得到一種對象也能夠,看具體需求。
public class RestaurantFactory { public Food getHamburger() { return new Hamburger(); } public Food getSteak() { return new Steak(); } }
靜態工廠只是在普通工廠上作一些小小的改變,意味着,工廠裏的建立對象方法改寫爲靜態方法,如此以來,就不須要new Factory 再操做工廠生成對象了。
public class RestaurantFactory { public static Food getHamburger() { return new Hamburger(); } public static Food getSteak() { return new Steak(); } } public static void main(String[] args) { // 利用靜態工廠建立對象 Food hamburger = RestaurantFactory.getHamburger(); Food steak = RestaurantFactory.getSteak(); hamburger.eat(); steak.eat(); }
每次須要建立新的對象的時候,就得去修改工廠類,這明顯違背了面向對象設計中的「開閉原則」。
工廠方法在簡單工廠上作了抽象處理。
把具體工廠抽象出了一個超級工廠,全部的具體工廠都實現這個抽象的超級工廠。客戶端經過訪問具體工廠的工廠方法來建立產品。
工廠方法模式的主要角色以下。
// 抽象工廠 public abstract class FoodAbstractFactory { public abstract Food getFood(); } // 具體工廠 麥當勞, Hamburger實現Food接口 public class McDonaldFactory extend FoodAbstractFactoty { @Override public Food getFood() { return new Hamburger(); } } // 具體工廠 咖啡廳, Steak實現Food接口 public class CafeFactory extend FoodAbstractFactoty { @Override public Food getFood() { return new Steak(); } } // Main函數 public static void main(String[] args) { // 工廠方法建立對象 FoodAbstractFactory mcDonald = new McDonaldFactory(); FoodAbstractFactory cafe = new CafeFactory(); Food hamburger = mcDonald.getFood(); Food steak = cafe.getFood(); hamburger.eat(); steak.eat(); }
工廠方法模式一般適用於如下場景。
工廠方法模式的主要優勢有:
其缺點是:
當須要生成的產品很少且不會增長,一個具體工廠類就能夠完成任務時,可刪除抽象工廠類。這時工廠方法模式將退化到簡單工廠模式
前面介紹的工廠方法模式中考慮的是一類產品的生產,如畜牧場只養動物、電視機廠只生產電視機、計算機軟件學院只培養計算機軟件專業的學生等。
同種類稱爲同等級,也就是說:工廠方法模式只考慮生產同等級的產品,可是在現實生活中許多工廠是綜合型的工廠,能生產多等級(種類) 的產品,如農場裏既養動物又種植物,電器廠既生產電視機又生產洗衣機或空調,大學既有軟件專業又有生物專業等。
本節要介紹的抽象工廠模式將考慮多等級產品的生產,將同一個具體工廠所生產的位於不一樣等級的一組產品稱爲一個產品族
抽象工廠的意義是確實比較抽象。。。它主要用於建立 對象家族 。下面舉例說明,更好理解它主要解決的問題。
好比我如今手機上安裝了一款App,我想在這個App上實現換膚功能。(包括配色和ui風格)
那麼,咱們就能夠理解爲,換膚功能就是一個抽象工廠,而功能中提供的每一種皮膚,就是一個具體工廠類。
每當咱們修改了皮膚主題,通常都會須要咱們重啓App,因而App會根據已選的皮膚主題,找到對應的具體皮膚主題工廠,進行UI初始化,包括ui配色,button風格,slider特效等等......
在以上的換膚過程裏,咱們能夠發現,皮膚主題工廠最終初始化出來的對象們都是不一樣類的,好比 Color,Button,Slider,Bar,Table。那麼以上這些類實例就能夠看做是主題工廠產生的對象家族。
上面的解釋若是不太明白,就直接看代碼吧。仍是餐廳例子。餐廳除了食物,還會生產飲品,餐具等等。也就是說,食物,飲品和餐具就是餐廳抽象工廠定義的對象家族。看代碼
// 抽象餐廳工廠 public abstract class RestaurantFactory { public abstract Food getFood(); public abstract Drinks getDrinks(); public abstract Item getItem(); } // 具體工廠 麥當勞, Hamburger實現Food接口,Cock實現Drinks,Tissue實現Item public class McDonaldFactory extend FoodAbstractFactoty { @Override public Food getFood() { return new Hamburger(); } @Override public Drinks getDrinks() { return new Cock(); } @Override public Item getItem() { return new Tissue(); } } // 具體工廠 咖啡廳, Steak實現Food接口,Coffee實現Drinks,Knife實現Item public class CafeFactory extend FoodAbstractFactoty { @Override public Food getFood() { return new Steak(); } @Override public Drinks getDrinks() { return new Coffee(); } @Override public Item getItem() { return new Knife(); } } // Main函數 public static void main(String[] args) { // 抽象工廠建立對象 FoodAbstractFactory mcDonald = new McDonaldFactory(); FoodAbstractFactory cafe = new CafeFactory(); Food hamburger = mcDonald.getFood(); Drinks cock = mcDonald.getDrinks(); Item tissue = mcDonald.getItem(); Food steak = cafe.getFood(); Drinks coffee = cafe.getDrinks(); Item knife = cafe.getItem(); hamburger.eat(); steak.eat(); cock.drink(); coffee.drink(); tissue.use(); knift.use(); }
抽象工廠模式最先的應用是用於建立屬於不一樣操做系統的視窗構件。如 java 的 AWT 中的 Button 和 Text 等構件在 Windows 和 UNIX 中的本地實現是不一樣的。
抽象工廠模式一般適用於如下場景:
抽象工廠模式的擴展有必定的「開閉原則」傾斜性:
另外一方面,當系統中只存在一個等級結構的產品時,抽象工廠模式將退化到工廠方法模式。