工廠模式 Factory
介紹
工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一,這種型別的設計模式屬于創建型模式,它提供了一種創建物件的最佳方式,
在工廠模式中,我們在創建物件時不會對客戶端暴露創建邏輯,并且是通過使用一個共同的介面來指向新創建的物件,
前言
工廠模式主要分為三種形式
-
簡單工廠模式(不屬于GoF的23種設計模式中)
-
工廠方法模式
-
抽象工廠模式
簡單來說,本質上工廠模式是對創建物件程序的一種封裝,通過封裝,讓客戶端無需在意物件創建的程序和邏輯,看看下面的例子,
本文部分解釋摘錄自 http://c.biancheng.net/view/1351.html
簡單工廠模式
比如我們去一家餐廳,我們想要點餐吃飯,
那么可以看作是客戶得到了飲料,食物,餐具,然后一一使用,我們先以下單食物為例,寫個例子,
不使用工廠模式時是這樣的
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();
}
簡單工廠模式的缺點
每次需要創建新的物件的時候,就得去修改工廠類,這明顯違背了面向物件設計中的“開閉原則”,
工廠方法模式
工廠方法在簡單工廠上做了抽象處理,
把具體工廠抽象出了一個超級工廠,所有的具體工廠都實作這個抽象的超級工廠,客戶端通過訪問具體工廠的工廠方法來創建產品,
結構
工廠方法模式的主要角色如下,
- 抽象工廠(Abstract Factory):提供了創建產品的介面,呼叫者通過它訪問具體工廠的工廠方法 newProduct() 來創建產品,
- 具體工廠(ConcreteFactory):主要是實作抽象工廠中的抽象方法,完成具體產品的創建,
- 抽象產品(Product):定義了產品的規范,描述了產品的主要特性和功能,
- 具體產品(ConcreteProduct):實作了抽象產品角色所定義的介面,由具體工廠來創建,它同具體工廠之間一一對應,

在例子中實作
// 抽象工廠
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();
}
適用場景
工廠方法模式通常適用于以下場景,
- 客戶只知道創建產品的工廠名,而不知道具體的產品名,如 TCL 電視工廠、海信電視工廠等,
- 創建物件的任務由多個具體子工廠中的某一個完成,而抽象工廠只提供創建產品的介面,
- 客戶不關心創建產品的細節,只關心產品的品牌,
優缺點
工廠方法模式的主要優點有:
- 用戶只需要知道具體工廠的名稱就可得到所要的產品,無須知道產品的具體創建程序;
- 在系統增加新的產品時只需要添加具體產品類和對應的具體工廠類,無須對原工廠進行任何修改,滿足開閉原則;
其缺點是:
- 每增加一個產品就要增加一個具體產品類和一個對應的具體工廠類,這增加了系統的復雜度,
模式的擴展
當需要生成的產品不多且不會增加,一個具體工廠類就可以完成任務時,可洗掉抽象工廠類,這時工廠方法模式將退化到簡單工廠模式
抽象工廠模式
介紹
前面介紹的工廠方法模式中考慮的是一類產品的生產,如畜牧場只養動物、電視機廠只生產電視機、計算機軟體學院只培養計算機軟體專業的學生等,
同種類稱為同等級,也就是說:工廠方法模式只考慮生產同等級的產品,但是在現實生活中許多工廠是綜合型的工廠,能生產多等級(種類) 的產品,如農場里既養動物又種植物,電器廠既生產電視機又生產洗衣機或空調,大學既有軟體專業又有生物專業等,
本節要介紹的抽象工廠模式將考慮多等級產品的生產,將同一個具體工廠所生產的位于不同等級的一組產品稱為一個產品族

舉例解釋
抽象工廠的意義是確實比較抽象,,,它主要用于創建 物件家族 ,下面舉例說明,更好理解它主要解決的問題,
比如我現在手機上安裝了一款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 中的本地實作是不同的,
抽象工廠模式通常適用于以下場景:
- 當需要創建的物件是一系列相互關聯或相互依賴的產品族時,如電器工廠中的電視機、洗衣機、空調等,
- 系統中有多個產品族,但每次只使用其中的某一族產品,如有人只喜歡穿某一個品牌的衣服和鞋,
- 系統中提供了產品的類別庫,且所有產品的介面相同,客戶端不依賴產品實體的創建細節和內部結構,
模式的擴展
抽象工廠模式的擴展有一定的“開閉原則”傾斜性:
- 當增加一個新的產品族時只需增加一個新的具體工廠,不需要修改原代碼,滿足開閉原則,
- 當產品族中需要增加一個新種類的產品時,則所有的工廠類都需要進行修改,不滿足開閉原則,
另一方面,當系統中只存在一個等級結構的產品時,抽象工廠模式將退化到工廠方法模式,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/1074.html
標籤:設計模式
上一篇:行為型模式之訪問者模式
下一篇:行為型模式之備忘錄模式
