引言
抽象工廠模式是基于工廠模式之上的另一種創(chuàng)造性的設(shè)計(jì)模式,是工廠模式的一種抽象;基于工廠模式的案例抽象出抽象工廠模式。
抽象工廠模式設(shè)計(jì)全球化汽車(chē)工廠
在工廠模式中我們將不同類(lèi)型的汽車(chē)使用工廠流水線來(lái)生產(chǎn),隱藏其復(fù)雜的生產(chǎn)邏輯(構(gòu)建過(guò)程);假如我們生產(chǎn)的汽車(chē)是面向全球地區(qū)的,那么應(yīng)該如何讓我們的生產(chǎn)面向全球化。
為了支持全球化運(yùn)營(yíng),我們需要增強(qiáng)我們應(yīng)用程序,以便生產(chǎn)出支持不同國(guó)家地區(qū)風(fēng)格的汽車(chē),比如我們國(guó)家汽車(chē)的駕駛室在前排左側(cè),而美國(guó)等歐洲國(guó)家駕駛室在前排的右側(cè),我們必須支持這種差異化生產(chǎn)。
為了描述抽象工廠模式,我們將考慮3種產(chǎn)品 - 美國(guó),亞洲和默認(rèn)(所有其他國(guó)家),支持多個(gè)位置需要進(jìn)行關(guān)鍵的設(shè)計(jì)更改。
為了支持這種多樣化的生產(chǎn)細(xì)節(jié),我們需要增加工廠流水線,即USACarFactory,AsiaCarFactory和DefaultCarFactory。在新增3條流水線之后,我們的工廠便足以能夠面向多樣化生產(chǎn),而使用者只需要通過(guò)抽象工廠類(lèi)來(lái)制造自己想要的汽車(chē),不要關(guān)注其中的細(xì)節(jié)。
抽象工廠是基于工廠類(lèi)的基礎(chǔ)上的再一層抽象,我們需要將工廠類(lèi)根據(jù)不同類(lèi)型進(jìn)行改造,然后在抽象工廠中對(duì)新流水線進(jìn)行再次抽象。
抽象工廠的解決方案
抽象工廠封裝類(lèi)圖:

使用CarFactory隱藏位置工廠的生產(chǎn)細(xì)節(jié)。
抽象工廠實(shí)現(xiàn)
為汽車(chē)新增Location屬性:
package com.iblog.pattern.factory;
public enum Location {
DEFAULT, USA, ASIA
}
抽象工廠類(lèi)實(shí)現(xiàn):
package com.iblog.pattern.factory;
public abstract class Car {
private CarType model;
private Location location;
public Car(CarType model, Location location) {
this.model = model;
this.location = location;
}
private void arrangeParts() {
// Do one time processing here
}
// Do subclass level processing in this method
protected abstract void construct();
public CarType getModel() {
return model;
}
public void setModel(CarType model) {
this.model = model;
}
}
將Location屬性增加至各種汽車(chē)模型中(LuxuryCar):
package com.iblog.pattern.factory;
public class LuxuryCar extends Car {
LuxuryCar(Location location) {
super(CarType.LUXURY, location);
construct();
}
@Override
protected void construct() {
System.out.println("Building luxury car");
// add accessories
}
}
將之前的工廠實(shí)現(xiàn)根據(jù)Location屬性進(jìn)行抽象:
package com.iblog.pattern.factory;
public class USACarFactory {
public static Car buildCar(CarType model) {
Car car = null;
switch (model) {
case SMALL:
car = new SmallCar(Location.USA);
break;
case SEDAN:
car = new SedanCar(Location.USA);
break;
case LUXURY:
car = new LuxuryCar(Location.USA);
break;
default:
//throw some exception
break;
}
return car;
}
}
package com.iblog.pattern.factory;
public class AsiaCarFactory {
public static Car buildCar(CarType model) {
Car car = null;
switch (model) {
case SMALL:
car = new SmallCar(Location.ASIA);
break;
case SEDAN:
car = new SedanCar(Location.ASIA);
break;
case LUXURY:
car = new LuxuryCar(Location.ASIA);
break;
default:
//throw some exception
break;
}
return car;
}
}
package com.iblog.pattern.factory;
public class DefaultCarFactory {
public static Car buildCar(CarType model) {
Car car = null;
switch (model) {
case SMALL:
car = new SmallCar(Location.DEFAULT);
break;
case SEDAN:
car = new SedanCar(Location.DEFAULT);
break;
case LUXURY:
car = new LuxuryCar(Location.DEFAULT);
break;
default:
//throw some exception
break;
}
return car;
}
}
然后我們?cè)?個(gè)Location工廠之上抽象出來(lái)一個(gè)新的抽象工廠類(lèi),我們通過(guò)不同Location工廠類(lèi)來(lái)生產(chǎn)汽車(chē):
package com.iblog.pattern.factory;
public class CarFactory {
private CarFactory() {
//Prevent instantiation
}
public static Car buildCar(CarType model) {
Car car = null;
//Read location property somewhere from configuration, also as a param.
Location location = Location.USA;
//Use location specific car factory
switch (location) {
case USA:
car = USACarFactory.buildCar(model);
break;
case ASIA:
car = AsiaCarFactory.buildCar(model);
break;
case DEFAULT:
car = DefaultCarFactory.buildCar(model);
break;
default:
// throw some exception
break;
}
return car;
}
}
測(cè)試:
package com.iblog.pattern.factory;
import org.junit.Test;
import static org.junit.Assert.*;
public class CarFactoryTest {
@Test
public void buildCar() {
System.out.println(CarFactory.buildCar(CarType.SMALL));
System.out.println(CarFactory.buildCar(CarType.SEDAN));
System.out.println(CarFactory.buildCar(CarType.LUXURY));
}
}
結(jié)果:
Building small car
com.iblog.pattern.factory.SmallCar@5b80350b
Building sedan car
com.iblog.pattern.factory.SedanCar@5d6f64b1
Building luxury car
com.iblog.pattern.factory.LuxuryCar@32a1bec0
Summary
當(dāng)我們?cè)诠S模式實(shí)現(xiàn)中需要對(duì)工廠進(jìn)行抽象編程時(shí),應(yīng)用抽象工廠實(shí)現(xiàn),與工廠模式之間多了一層抽象邏輯,在Jdk中抽象工廠模式也是常見(jiàn)的: