概述
工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式。工廠模式提供了一種將對象的實例化過程封裝在工廠類中的方式。通過使用工廠模式,可以將對象的創(chuàng)建與使用代碼分離,提供一種統(tǒng)一的接口來創(chuàng)建不同類型的對象。
先看一個例子,首先定義一個 Coffee 抽象類,作為所有咖啡的基類。
public abstract class Coffee {
String name;
public Coffee(String name) {
this.name = name;
}
abstract void addMilk(AMOUNT amount);
abstract void addSugar(AMOUNT amount);
abstract void addIce(AMOUNT amount);
public String getName() {
return name;
}
}
再定義兩種咖啡:
public class AmericanCoffee extends Coffee {
public AmericanCoffee() {
super("美式咖啡");
}
@Override
void addMilk(AMOUNT amount) {
System.out.println("美式咖啡其他行為");
System.out.println("添加" + amount.name() + "牛奶");
}
@Override
void addSugar(AMOUNT amount) {
System.out.println("美式咖啡其他行為");
System.out.println("美式咖啡不能添加糖");
}
@Override
void addIce(AMOUNT amount) {
System.out.println("美式咖啡其他行為");
System.out.println("添加" + amount.name() + "冰");
}
}
public class LatteCoffee extends Coffee {
public LatteCoffee() {
super("拿鐵咖啡");
}
@Override
void addMilk(AMOUNT amount) {
System.out.println("拿鐵咖啡其他行為");
System.out.println("添加" + amount.name() + "牛奶");
}
@Override
void addSugar(AMOUNT amount) {
System.out.println("拿鐵咖啡其他行為");
System.out.println("添加" + amount.name() + "糖");
}
@Override
void addIce(AMOUNT amount) {
System.out.println("拿鐵咖啡其他行為");
System.out.println("拿鐵咖啡不能添加冰");
}
}
最后定義一個咖啡店類:
public class CoffeeStore {
public Coffee orderCoffee(String coffeeType) {
if ("latte".equals(coffeeType)) {
return new LatteCoffee();
} else if ("american".equals(coffeeType)) {
return new AmericanCoffee();
} else {
throw new IllegalArgumentException();
}
}
}
其 UML 類圖如下:

我們可以看到CoffeeStore這個類和具體產(chǎn)品是耦合的,創(chuàng)建對象和使用對象的代碼放在一起意味著每一次我們添加一個新的咖啡種類時,都要更改 orderCoffee 這個方法,也就是要更改客戶端,這顯然違背了開閉原則;
而工廠模式的好處在于通過使用工廠模式,可以將對象的創(chuàng)建與使用代碼分離,提供一種統(tǒng)一的接口來創(chuàng)建不同類型的對象。工廠模式最簡單實現(xiàn)就是簡單工廠模式,簡單工廠模式定義了一個創(chuàng)建對象的類,由這個類來封裝實例化對象的行為,簡單工廠模式不是一種正式的設計模式,而是一種規(guī)范,他包含如下成員:
- 抽象產(chǎn)品 :定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能;
- 具體產(chǎn)品 :實現(xiàn)或者繼承抽象產(chǎn)品的子類;
- 具體工廠 :提供了創(chuàng)建產(chǎn)品的方法,調(diào)用者通過該方法來獲取產(chǎn)品。
為了實踐簡單工廠模式,我們創(chuàng)建一個新的類 CoffeeFactory,用于控制咖啡的創(chuàng)建,其代碼如下:
public class CoffeeFactory {
public static Coffee getCoffee(String coffeeType) {
if ("latte".equals(coffeeType)) {
return new LatteCoffee();
} else if ("american".equals(coffeeType)) {
return new AmericanCoffee();
} else {
throw new IllegalArgumentException();
}
}
}
其 UML 類圖如下:

通過添加一個簡單的咖啡工廠,這樣讓CoffeeStore和 Coffee 進行了解耦,雖然增加一個咖啡類還是需要更改CoffeeFactory的代碼,但需要修改的代碼量已經(jīng)大幅度下降。
工廠類是整個簡單工廠模式的關鍵。包含了必要的邏輯判斷,根據(jù)外界給定的信息,決定究竟應該創(chuàng)建哪個具體類的對象。通過使用工廠類,外界可以從直接創(chuàng)建具體產(chǎn)品對象的尷尬局面擺脫出來,僅僅需要負責使用創(chuàng)建出來的對象就可以了。而不必管這些對象究竟如何創(chuàng)建及如何組織的。明確了各自的職責和權利,有利于整個體系結構的優(yōu)化。
簡單工廠模式的問題在于 CoffeeFactory 和各種 Coffee 的耦合,為了解決這個問題,可以采用工廠方法模式,工廠方法模式的主要結構如下:
- 抽象工廠(Abstract Factory):提供了創(chuàng)建產(chǎn)品的接口,調(diào)用者通過它訪問具體工廠的工廠方法來創(chuàng)建產(chǎn)品。
- 具體工廠(ConcreteFactory):主要是實現(xiàn)抽象工廠中的抽象方法,完成具體產(chǎn)品的創(chuàng)建。
- 抽象產(chǎn)品(Product):定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能。
- 具體產(chǎn)品(ConcreteProduct):實現(xiàn)了抽象產(chǎn)品所定義的接口,由具體工廠來創(chuàng)建,它同具體工廠之間一一對應。
首先添加一個抽象工廠類 IFactory 以及其具體實現(xiàn)類(AmericanFactory、LatteFactory)
public interface IFactory {
Coffee getCoffee();
}
public class LatteFactory implements IFactory {
@Override
public Coffee getCoffee() {
return new LatteCoffee();
}
}
public class AmericanFactory implements IFactory {
@Override
public Coffee getCoffee() {
return new AmericanCoffee();
}
}
其 UML 類圖如下:

咖啡工廠喝咖啡一一對應,因此我們只要知道咖啡的名稱便可以使用對應的具體工廠直接創(chuàng)建出對應的咖啡;這就將 CoffeeFactory 和各種 Coffee 進行了解耦。工廠方法模式是簡單工廠模式的進一步抽象和推廣,由于使用了面向對象的多態(tài)性,工廠方法模式保持了簡單工廠模式的優(yōu)點,同時克服了它的缺點。添加新產(chǎn)品時,只需要添加對應的工廠實現(xiàn)類和產(chǎn)品類即可,滿足開閉原則;但是由于添加一個產(chǎn)品就得添加一個工廠,使用該模式會增加系統(tǒng)復雜度。
由于工廠方法模式中的每個工廠只生產(chǎn)一類產(chǎn)品,可能會導致系統(tǒng)中存在大量的工廠類,勢必會增加系統(tǒng)的開銷。此時,我們可以考慮將一些相關的產(chǎn)品組成一個產(chǎn)品族,由同一個工廠來統(tǒng)一生產(chǎn),這就是抽象工廠模式的基本思想。所謂產(chǎn)品族,舉一個簡單的例子,蘋果可以生產(chǎn)電腦和鼠標;微軟也可以生產(chǎn)電腦和鼠標;同一個公司生產(chǎn)的不同產(chǎn)品就是一個產(chǎn)品族,不同公司生產(chǎn)的同種產(chǎn)品只是產(chǎn)品等級不同的產(chǎn)品,抽象工廠的核心就是構建一個產(chǎn)品族的抽象工廠,他與工廠方法模式的最顯著區(qū)別在于一個工廠可以創(chuàng)建多個產(chǎn)品。其示例如下:

總結一下:工廠模式的意義在于【將實例化對象的代碼提取出來,放到一個類中統(tǒng)一管理和維護,達到和主項目的依賴關系的解耦】,從而提高項目的擴展和維護性。增加新的產(chǎn)品族很方便,無須修改已有系統(tǒng),符合“開閉原則”。其核心優(yōu)點是:
- 可以使代碼結構清晰,有效地封裝變化;
- 對調(diào)用者屏蔽具體的產(chǎn)品類,調(diào)用者不需要使用 new 關鍵字創(chuàng)建產(chǎn)品;
- 降低耦合度。
使用場景:當我們需要根據(jù)給定條件的不同創(chuàng)建不同的實例,就可以使用工廠方法模式,如果具體產(chǎn)品有產(chǎn)品族和產(chǎn)品等級兩個維度,那么可以考慮使用抽象工廠模式。
往期回顧
文中難免會出現(xiàn)一些描述不當之處(盡管我已反復檢查多次),歡迎在留言區(qū)指正,相關的知識點也可進行分享,希望大家都能有所收獲??!如果覺得我的文章寫得還行,不妨支持一下。你的每一個轉發(fā)、關注、點贊、評論都是對我最大的支持!