設計模式總的來說分爲3類:創建型模式(5種)、結構型模式(7種)、行爲型模式(11種),其中創建型模式分爲:單例模式、工廠方法模式、抽象工廠模式、建造者模式、原型模式,這裏要總結的就是創建型模式中的抽象工廠模式。
準備工作:
總結抽象工廠模式之前,先介紹兩個概念:產品族和產品等級結構(參考圖片)。
產品等級結構:源自同一抽象產品角色的不同具體產品位於同一產品等級。例如抽象產品角色爲冰箱接口,其子類有海爾冰箱和格力冰箱,海爾冰箱和格力冰箱它們是位於同一產品等級的,同理,海爾空調和格力空調也是位於同一產品等級。
產品族:同一工廠生產的,並處在不同產品等級結構中相同位置的產品構成一個產品族。例如有兩個工廠,一個是海爾電器工廠,一個是格力電器工廠。其中海爾電器工廠生產海爾冰箱和海爾空調,海爾冰箱和海爾空調一個是位於冰箱產品等級結構中,一個是位於空調的等級結構中,雖然產品等級結構不同,但是位置卻相同,故海爾冰箱和海爾空調構成一個產品族;格力冰箱和格力空調構成一個產品族。
抽象工廠模式:
爲什麼要使用抽象工廠模式?有了產品等級結構和產品族的概念,可以熟知工廠方法模式針對的都是同一產品等級結構,一個工廠只能生產一種產品,當一個工廠想要生產多個產品的時候(一個產品族),就需要使用到抽象工廠模式了。通俗的解釋一下,在工廠方法模式中,假設有兩個工廠,一個工廠生產冰箱,一個工廠生產空調,由於成本和人力的不斷提高,廠方決定引入新技術,縮減成本和人力,將兩個工廠乾的事情合併到一個工廠。但是有個前提條件,產品必須是位於不同產品等級的,不能一個工廠即生產海爾的冰箱由生產格力冰箱,這顯然是不符合邏輯的,會遭格力舉報的。
有了上面的鋪墊,現在來看看抽象工廠模式中各個角色和其職責:
抽象工廠角色: | 抽象工廠模式中的核心,它是一個抽象類或接口,所有具體工廠都要繼承或實現它。 |
具體工廠角色: | 具體工廠,負責產品的創建,即生成具體的對象。 |
抽象產品角色: | 工廠所創建實例的父類,所有產品都要實現該接口,或繼承該抽象類。 |
具體產品角色: | 具體的產品類,工廠的目的就是要創建這些產品類的實例。 |
抽象工廠模式的例子,使用海爾和格力產品的創建來說明。首先來創建兩個抽象產品角色:
/**
* 抽象產品角色:冰箱接口
*/
public interface FridgeInterface {
void function();
}
/**
* 抽象產品角色:空調接口
*/
public interface AirConditionInterface {
void functoin();
}
創建具體的產品角色,海爾冰箱和海爾空調
/**
* 具體產品角色:海爾冰箱
*/
public class HaierFridge implements FridgeInterface {
public HaierFridge() {
System.out.println("生產海爾冰箱");
}
@Override
public void function() {
System.out.println("海爾冰箱可以冰凍啤酒");
}
}
/**
* 具體產品角色:海爾空調
*/
public class HaierAirCondition implements AirConditionInterface {
public HaierAirCondition() {
System.out.println("生產海爾空調");
}
@Override
public void functoin() {
System.out.println("海爾空調可以調節室內溫度");
}
}
創建抽象工廠:
/**
* 抽象工廠角色:工廠創建的產品是一個產品族,但不是一個產品等級結構
*/
public interface HaierFactory {
HaierFridge getHaierFridge();
HaierAirCondition getHaierAirCondition();
}
接着創建一個工廠,該工廠既可以生產冰箱,又可以生產空調。
/**
* 具體工廠角色
*/
public class HaierFactoryImpl implements HaierFactory{
@Override
public HaierFridge getHaierFridge() {
return new HaierFridge();
}
@Override
public HaierAirCondition getHaierAirCondition() {
return new HaierAirCondition();
}
}
客戶端:
/**
* 客戶端
*/
public class Client {
public static void main(String[] args) {
HaierFactory factory= new HaierFactoryImpl();
factory.getHaierFridge();
factory.getHaierAirCondition();
}
}
控制檯打印:
生產海爾冰箱
生產海爾空調
優缺點分析:
優點:隔離了具體類的生成,使得客戶並不需要知道什麼被創建。由於這種隔離,更換一個具體工廠就變得相對容易。增加新的具體工廠和產品族很方便,無須修改已有系統,符合“開閉原則”。
缺點:在添加新的產品對象時,難以擴展抽象工廠來生產新種類的產品,這是因爲在抽象工廠角色中規定了所有可能被創建的產品集合,要支持新種類的產品就意味着要對該接口進行擴展,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會帶來較大的不便。開閉原則的傾斜性(增加新的工廠和產品族容易,增加新的產品等級結構麻煩)
。
參考文章:https://www.kancloud.cn/digest/xing-designpattern/143724