模式的定義與特點
抽象工廠(AbstractFactory)模式的定義:是一種爲訪問類提供一個創建一組相關或相互依賴對象的接口,且訪問類無須指定所要產品的具體類就能得到同族的不同等級的產品的模式結構。
抽象工廠模式是工廠方法模式的升級版本,工廠方法模式只生產一個等級的產品,而抽象工廠模式可生產多個等級的產品。
使用抽象工廠模式一般要滿足以下條件。
- 系統中有多個產品族,每個具體工廠創建同一族但屬於不同等級結構的產品。
- 系統一次只可能消費其中某一族產品,即同族的產品一起使用。
抽象工廠模式除了具有工廠方法模式的優點外,其他主要優點如下。
- 可以在類的內部對產品族中相關聯的多等級產品共同管理,而不必專門引入多個新的類來進行管理。
- 當增加一個新的產品族時不需要修改原代碼,滿足開閉原則。
其缺點是:當產品族中需要增加一個新的產品時,所有的工廠類都需要進行修改。
模式的結構與實現
抽象工廠模式同工廠方法模式一樣,也是由抽象工廠、具體工廠、抽象產品和具體產品等 4 個要素構成,但抽象工廠中方法個數不同,抽象產品的個數也不同。現在我們來分析其基本結構和實現方法。
1. 模式的結構
抽象工廠模式的主要角色如下。
- 抽象工廠(Abstract Factory):提供了創建產品的接口,它包含多個創建產品的方法 newProduct(),可以創建多個不同等級的產品。
- 具體工廠(Concrete Factory):主要是實現抽象工廠中的多個抽象方法,完成具體產品的創建。
- 抽象產品(Product):定義了產品的規範,描述了產品的主要特性和功能,抽象工廠模式有多個抽象產品。
- 具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來創建,它 同具體工廠之間是多對一的關係。
抽象工廠模式的結構如下圖所示:
接着工廠方法的例子,結構如下圖所示:
public abstract class AbstractPizza {
protected String name;
public void prepare() {
System.out.println(name + "材料正在準備");
}
public void bake() {
System.out.println(name + "正在烤");
}
public void cut() {
System.out.println(name + "正在切割");
}
public void box() {
System.out.println(name + "正在包裝");
}
}
public class BJCheesePizza extends AbstractPizza {
public BJCheesePizza() {
this.name = "北京芝士披薩";
}
}
BJSeafoodPizza、LDCheesePizza、LDSeafoodPizza 類類似,參考BJCheesePizza
public class AbstractChip {
protected String name;
public void deepFired() {
System.out.println(name + "正在油炸");
}
}
public class BJChip extends AbstractChip {
public BJChip() {
this.name = "北京薯條";
}
}
LDChip類似,參考BJChip
public abstract class AbstractPizzaFactory {
public abstract AbstractPizza createPizza(String orderType);
/**
* 訂購pizza
*
* @param orderType
* @return
*/
public AbstractPizza orderPizza(String orderType) {
AbstractPizza pizza = createPizza(orderType);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
public abstract AbstractChip createChip();
/**
* 訂購薯條
*
* @return
*/
public AbstractChip orderChip() {
AbstractChip chip = createChip();
chip.deepFired();
return chip;
}
}
public class BJFactory extends AbstractPizzaFactory {
@Override
public AbstractPizza createPizza(String orderType) {
AbstractPizza pizza = null;
if (orderType.equals("seafood")) {
pizza = new BJSeafoodPizza();
} else if (orderType.equals("cheese")) {
pizza = new BJCheesePizza();
}
return pizza;
}
@Override
public AbstractChip createChip() {
return new BJChip();
}
}
LDFactory 類似,參考 BJFactory
public class Client {
public static void main(String[] args) {
AbstractPizzaFactory ldPizzaFactory = new LDFactory();
AbstractPizza ldCheesePizza = ldPizzaFactory.orderPizza("seafood");
AbstractPizzaFactory bjFactory = new BJFactory();
AbstractChip bjChip = bjFactory.orderChip();
}
}
模式的應用場景
抽象工廠模式最早的應用是用於創建屬於不同操作系統的視窗構件。如 java 的 AWT 中的 Button 和 Text 等構件在 Windows 和 UNIX 中的本地實現是不同的。
抽象工廠模式通常適用於以下場景:
- 當需要創建的對象是一系列相互關聯或相互依賴的產品族時,如電器工廠中的電視機、洗衣機、空調等。
- 系統中有多個產品族,但每次只使用其中的某一族產品。如有人只喜歡穿某一個品牌的衣服和鞋。
- 系統中提供了產品的類庫,且所有產品的接口相同,客戶端不依賴產品實例的創建細節和內部結構。
模式的擴展
抽象工廠模式的擴展有一定的“開閉原則”傾斜性:
- 當增加一個新的產品族時只需增加一個新的具體工廠,不需要修改原代碼,滿足開閉原則。
- 當產品族中需要增加一個新種類的產品時,則所有的工廠類都需要進行修改,不滿足開閉原則。
另一方面,當系統中只存在一個等級結構的產品時,抽象工廠模式將退化到工廠方法模式。