抽象工廠模式
介紹
抽象工廠模式可以說是是工廠方法模式的升級版,當需要創建的產品有多個產品線(產品族)時,使用抽象工廠模式是比較好的選擇。
簡單地說就是工廠的工廠,抽象工廠可以創建具體工廠,由具體工廠來產生具體產品。
在抽象工廠模式中有如下角色:
- AbstractFactory:抽象工廠,它聲明瞭用來創建不同產品的方法。
- ConcreteFactory:具體工廠,實現抽象工廠中定義的創建產品的方法。
- AbstractProduct:抽象產品,爲每種產品聲明業務方法。
- ConcreteProduct:具體產品,定義具體工廠生產的具體產品,並實現抽象產品中定義的業務方法。
代碼實現
場景:
- 現在有2個產品族,一個水果,一個必需品
- 水果有2種,蘋果,香蕉
- 必需品也有2種,大米,鹽
- 工廠生產的東西必須包含一種水果,一種必需品
產品族
public interface AbstractFruit {
void produceFruit();
}
public interface AbstractNecessities {
void produceNecessities();
}
具體產品
// 具體產品1(蘋果)
public class AppleA implements AbstractFruit{
@Override
public void produceFruit() {
System.out.println("抽象工廠...生產水果...apple...");
}
}
// 具體產品2(香蕉)
public class BananaA implements AbstractFruit {
@Override
public void produceFruit() {
System.out.println("抽象工廠...生產水果...banana...");
}
}
// 具體產品3(鹽)
public class SaltA implements AbstractNecessities {
@Override
public void produceNecessities() {
System.out.println("抽象工廠...生產必需品...salt...");
}
}
// 具體產品4(大米)
public class RiceA implements AbstractNecessities {
@Override
public void produceNecessities() {
System.out.println("抽象工廠...生產必需品...rice...");
}
}
以上是縱向關係,蘋果、香蕉繼承於水果,鹽、大米繼承於必需品
現在構建工廠,首先一個父工廠(抽象工廠),然後兩個具體工廠
// 定義 生產 產品工廠 的抽象工廠
public interface AbstractFactory {
AbstractFruit produceFruit();
AbstractNecessities produceNecessities();
}
2個具體工廠
// 具體工廠1號,本工廠職責:只生產蘋果和鹽
public class AppleAndSaltFactory implements AbstractFactory {
@Override
public AbstractFruit produceFruit() {
return new AppleA();
}
@Override
public AbstractNecessities produceNecessities() {
return new SaltA();
}
}
// 具體工廠2號,本工廠職責:只生產香蕉和大米
public class BananaAndRiceFactory implements AbstractFactory {
@Override
public AbstractFruit produceFruit() {
return new BananaA();
}
@Override
public AbstractNecessities produceNecessities() {
return new RiceA();
}
}
工廠的使用
public class AbstractClient {
public static void main(String[] args) {
AbstractFactory appleAndSaltFactory = new AppleAndSaltFactory();
appleAndSaltFactory.produceFruit().produceFruit();
appleAndSaltFactory.produceNecessities().produceNecessities();
AbstractFactory bananaAndRiceFactory = new BananaAndRiceFactory();
bananaAndRiceFactory.produceFruit().produceFruit();
bananaAndRiceFactory.produceNecessities().produceNecessities();
}
}
/* 運行結果
抽象工廠...生產水果...apple...
抽象工廠...生產必需品...salt...
抽象工廠...生產水果...banana...
抽象工廠...生產必需品...rice...
*/
抽象工廠的優缺點
優點
- 抽象工廠模式隔離了具體類的生成,使得客戶並不需要知道什麼被創建。
- 當一個產品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的對象。這對一些需要根據當前環境來決定其行爲的軟件系統來說,是一種非常實用的設計模式。
- 增加新的具體工廠和產品族很方便,無須修改已有系統,符合“開閉原則”。
缺點
- 在添加新的產品對象時,難以擴展抽象工廠來生產新種類的產品。因爲在抽象工廠角色中規定了所有可能被創建的產品集合,要支持新種類的產品就意味着要對該接口進行擴展,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會帶來較大的不便
- 使用抽象工廠模式要求設計人員在設計之初就能夠全面考慮,不會在設計完成之後向系統中增加新的產品等級結構,也不會刪除已有的產品等級結構,否則將會導致系統出現較大的修改,爲後續維護工作帶來諸多麻煩。
小結(應用場景)
先看優缺點!
這個例子有點欠佳,看到這裏,如果還不明白抽象工廠,接下來舉一個進行擴展的例子,你應該就可以明白了。
1. 橫向拓展易
如果增加新的具體工廠(就是所謂的產品族),比如,新增一個 只生產蘋果和大米的工廠。
那麼,不需要修改原有的代碼,只需要新增一個工廠類 AppleAndRiceFactory implements AbstractFactory
即可。
2. 縱向擴展難
比如,新增一類產品 — 家電(相當於新增具體的產品)。
要想工廠具有生產家電的功能,就需要修改 AbstractFactory
的代碼,新增加一個生產家電的方法,那麼就需要重新構建所有實現了 AbstractFactory
接口的類,極爲複雜。
簡單工廠、工廠方法、抽象工廠區別
簡單工廠 : 用來生產同一等級結構中的任意產品。(不支持拓展增加產品)
工廠方法 :用來生產同一等級結構中的固定產品。(支持拓展增加產品)
抽象工廠 :用來生產不同產品族的全部產品。(不支持拓展增加產品;支持增加產品族)
工廠設計模式