在工廠方法模式中具體工廠負(fù)責(zé)生產(chǎn)具體的產(chǎn)品,每一個具體工廠對應(yīng)一種具體產(chǎn)品,工廠方法具有唯一性,一般情況下,一個具體工廠中只有一個或者一組重載的工廠方法。但是有時候我們希望一個工廠可以提供多個產(chǎn)品對象,而不是單一的產(chǎn)品對象,如一個地圖工廠,它可以生產(chǎn)院內(nèi)地圖、院外地圖,而不是只生產(chǎn)一種地圖。
-
產(chǎn)品等級結(jié)構(gòu)
產(chǎn)品等級結(jié)構(gòu)即產(chǎn)品的繼承結(jié)構(gòu),如一個抽象類是院外地圖,其子類百度院外地圖、高德院外地圖、廣義恒鑫院外地圖。則抽象院外地圖與具體的院外地圖之間構(gòu)成了一個產(chǎn)品等級結(jié)構(gòu),抽象院外地圖是父類,而具體的院外地圖是其子類。
-
產(chǎn)品族
在抽象工廠模式中,產(chǎn)品族是指由同一個工廠生產(chǎn)的,位于不同產(chǎn)品等級結(jié)構(gòu)中的一組產(chǎn)品,如百度地圖工廠生產(chǎn)的百度院內(nèi)地圖、百度院外地圖。那么百度院內(nèi)地圖位于院內(nèi)地圖等級結(jié)構(gòu)中,百度院外地圖位于院外地圖等級結(jié)構(gòu)中,百度院內(nèi)地圖、百度院外地圖構(gòu)成了一個產(chǎn)品族。
-
AbstractFactory(抽象工廠)
它聲明了一組用于創(chuàng)建一族產(chǎn)品的方法,每一個方法對應(yīng)一種產(chǎn)品。
public interface MapFactory {
GWIOutdoorMapBaseLayout createOutdoorMapView(Context context);
GWIIndoorMapBaseLayout createIndoorMapView(Context context);
}
-
ConcreteFactory(具體工廠)
它實現(xiàn)了在抽象工廠中聲明的創(chuàng)建產(chǎn)品的方法,生成一組具體產(chǎn)品,這些產(chǎn)品構(gòu)成了一個產(chǎn)品族,每一個產(chǎn)品都位于某個產(chǎn)品等級結(jié)構(gòu)中。
public class BaiduMapFactory implements MapFactory {
@Override
public GWIOutdoorMapBaseLayout createOutdoorMapView(Context context) {
//返回百度地圖的院外地圖
}
@Override
public GWIIndoorMapBaseLayout createIndoorMapView(Context context) {
//返回百度地圖的院內(nèi)地圖
}
}
-
AbstractProduct(抽象產(chǎn)品)
它為每種產(chǎn)品聲明接口,在抽象產(chǎn)品中聲明了產(chǎn)品所具有的業(yè)務(wù)方法。
public interface GWIOutdoorMapBaseLayout {
void display();
}
-
ConcreteProduct(具體產(chǎn)品)
它定義具體工廠生產(chǎn)的具體產(chǎn)品對象,實現(xiàn)抽象產(chǎn)品接口中聲明的業(yè)務(wù)方法。
public class GWIBaiduOutdoorMapLayout extends GWIOutdoorMapBaseLayout {
@Override
public void display() {
//顯示百度地圖的院外地圖
}
}
-
調(diào)用方式
通過創(chuàng)建一個工廠的實例,來得到對應(yīng)的院內(nèi)地圖和院外地圖。
MapFactory mapFactory = new BaiduMapFactory();
GWIBaiduOutdoorMapLayout gwiBaiduOutdoorMapLayout = mapFactory.createOutdoorMapView(this);
GWIBaiduIndoorMapLayout gwiBaiduIndoorMapLayout = mapFactory.createIndoorMapView(this);
gwiBaiduOutdoorMapLayout.display();
gwiBaiduIndoorMapLayout.display();
- 抽象工廠模式通過把產(chǎn)品劃分為族的概念,來減少工廠類的個數(shù),即一個工廠類不再是單一的生產(chǎn)一個產(chǎn)品而是生產(chǎn)一族產(chǎn)品,這一族產(chǎn)品必定會有個約束才能稱作是一族,以上舉的例子中,假如百度院內(nèi)地圖和百度院外地圖需要同時顯示,這個就是一個約束,所以可以把它們看成是一個族。
- 抽象工廠模式解決了工廠模式的一個問題,即工廠模式中如果有大量的子類對象,那么就會有大量的具體工廠類。但是抽象工廠模式也有一個缺點,就是在抽象工廠模式設(shè)計最初,就要考慮好產(chǎn)品的等級結(jié)構(gòu),例如地圖分為院內(nèi)地圖和院外地圖,保證以后不會再增加院X地圖。因為抽象工廠模式,對于增加一個產(chǎn)品族,如加入高德的院內(nèi)院外地圖可以不修改原有代碼,遵循了開閉原則,但是對于增加等級結(jié)構(gòu)或者說是修改等級結(jié)構(gòu),那么會需要修改抽象工廠類的代碼,這樣會導(dǎo)致底下所有的工廠類都需要修改。這也被稱作是抽象工廠模式的開閉原則的傾斜性。即支持增加新的產(chǎn)品族但是不支持增加新的產(chǎn)品結(jié)構(gòu)。