在上篇文章中我們用肉鋪這樣一個場景描述了簡單工廠模式,肉鋪老板賣的不同品種的豬肉,設想隨著時間的消逝,肉鋪的生意日趨紅火,客戶要求增加鴨、雞、牛等之類的肉,這樣我們就要分別引進亞洲鴨、非洲鴨,亞洲雞、非洲雞等等,很明顯原先的軟件設計就顯的很無力了,根本適應不了現今的狀態。所以就引進了抽象工廠模式。
抽象工廠模式是所有形態的工廠模式中最為抽象和最具一般性的一種形態。
為了方便引進抽象工廠模式,引進一個新概念:產品族(Product Family)。所謂產品族,是指位于不同產品等級結構,功能相關聯的產品組成的家族。如圖:

圖中一共有四個產品族,分布于三個不同的產品等級結構中。只要指明一個產品所處的產品族以及它所屬的等級結構,就可以唯一的確定這個產品。
所謂的抽象工廠是指一個工廠等級結構可以創建出分屬于不同產品等級結構的一個產品族中的所有對象。如果用圖來描述的話,如下圖:

AbstractFactory模式的結構如下:

圖中AfricanPig和AsiaPig構成一個等級結構,AfiricanPorkFactory生產出來的包括AfricanPig和AfricanDuck構成一個產品族。
抽象工廠(Abstract Factory)角色:擔任這個角色的是工廠方法模式的核心,它是與應用系統商業邏輯無關的。
具體工廠(Concrete Factory)角色:這個角色直接在客戶端的調用下創建產品的實例。這個角色含有選擇合適的產品對象的邏輯,而這個邏輯是與應用系統的商業邏輯緊密相關的。
抽象產品(Abstract Product)角色:擔任這個角色的類是工廠方法模式所創建的對象的父類,或它們共同擁有的接口。
具體產品(Concrete Product)角色:抽象工廠模式所創建的任何產品對象都是某一個具體產品類的實例。這是客戶端最終需要的東西,其內部一定充滿了應用系統的商業邏輯。
上圖的程序如下:
public interface Duck {
public void send();
}
public class AsiaDuck implements Duck {
public void send() {
System.out.println("send Asia duck");
}
}
public class AfricanDuck implements Duck {
public void send() {
System.out.println("send African duck");
}
}
public interface Pig {
public void send();
}
public class AsiaPig implements Pig {
public void send() {
System.out.println("send Asia pig");
}
}
public class AfricanPig implements Pig {
public void send() {
System.out.println("send African pig");
}
}
public abstract class AbstractFactory {
public abstract Pig createPig();
public abstract Duck createDuck();
}
public class AfricanPorkFactory extends AbstractFactory {
@Override
public Duck createDuck() {
return new AfricanDuck();
}
@Override
public Pig createPig() {
return new AfricanPig();
}
}
public class AsiaPorkFactory extends AbstractFactory {
@Override
public Duck createDuck() {
return new AsiaDuck();
}
@Override
public Pig createPig() {
return new AsiaPig();
}
}
public class PorkStoreClient {
private Pig pig = null;
private Duck duck = null;
public PorkStoreClient(AbstractFactory factory) {
pig = factory.createPig();
duck = factory.createDuck();
}
public void send() {
pig.send();
duck.send();
}
public static void main(String[] args) {
AbstractFactory africanFactory = new AfricanPorkFactory();
PorkStoreClient africanPorkStore = new PorkStoreClient(africanFactory);
africanPorkStore.send();
AbstractFactory asiaFactory = new AsiaPorkFactory();
PorkStoreClient asiaPorkStore = new PorkStoreClient(asiaFactory);
asiaPorkStore.send();
}
}
上述的場景可能不是很好的闡述了抽象工廠的應用,但我們如果換個場景呢?把text和button作為產品,而UnixText和UnixButton構成Unix產品族,WinText和WinButton作為Window產品族。還有汽車的零部件等等場景都能讓你更加了解抽象工廠的應用。
抽象工廠模式與工廠方法模式的區別
工廠方法模式是一種極端情況的抽象工廠模式,而抽象工廠模式可以看成是工廠方法模式的一種推廣。
(1)、工廠方法模式是用來創建一個產品的等級結構的,而抽象工廠模式是用來創建多個產品的等級結構的。工廠方法創建一般只有一個方法,創建一種產品。抽象工廠一般有多個方法,創建一系列產品。
(2)、工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個。工廠方法模式的具體工廠類只能創建一個具體產品類的實例,而抽象工廠模式可以創建多個。