如果您需要一組可以隨時抽換的元件,並且希望可以簡單地 一次抽換,則可以考慮使用Abstract Factory。例如視窗程式中視感(Look-and- feel)元件的調換,就是Abstract Factory的應用場合。
以下是Abstract Factory的簡單實現,程式中Rectangle依賴於PointCornerFactory的公開定義,使用PointCornerFactory 所提供的一組元件來繪製矩形:
interface PointCornerFactory {
Point getPoint();
Corner getCorner();
}
interface Point {
void line(int width);
}
interface Corner {
void leftUp();
void rightUp();
void leftDown();
void rightDown();
}
class Rectangle {
private int width;
private int height;
Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
void paint(PointCornerFactory factory) {
Point point = factory.getPoint();
Corner corner = factory.getCorner();
corner.leftUp();
point.line(width - 2);
corner.rightUp();
System.out.println();
for(int i = 0; i < height - 2; i++) {
point.line(width);
System.out.println();
}
corner.leftDown();
point.line(width - 2);
corner.rightDown();
System.out.println();
}
}
依您所提供的PointCornerFactory、Point與Corner實作之不同,可以繪製出不同外觀的矩形,例 如:
public class Main {
public static void main(String[] args) {
Rectangle rect = new Rectangle(20, 10);
PointCornerFactory factory =
new PointCornerFactory() {
public Point getPoint() {
return new Point() {
public void line(int width) {
for(int i = 0; i < width; i++) {
System.out.print("-");
}
}
};
}
public Corner getCorner() {
return new Corner() {
public void leftUp() { System.out.print('+'); }
public void rightUp() { System.out.print('+'); }
public void leftDown() { System.out.print('+'); }
public void rightDown() { System.out.print('+'); }
};
}
};
rect.paint(factory);
}
}
如果您要呈現不同的矩形外觀,則可以提供另一組PointCornerFactory、Point、 Conrer實作,對Rectangle而言,就可達成一次抽象所有元件的需求。
下圖為AbstractFactory的類別圖:
圖中AbstractFactory、Part指的是,物件必須具有AbstractFactory、Part所定義之公 開協定,而非專指Java中的interface定義。對於靜態語言來說,例如Java,必須使用型態來宣告變數,因此根 據需求,可以使用interfact或abstract class來定義AbstractFactory、Part所定 義之公開協定。對於動態語言來說,例如Python,真正的型態資訊是在物件之上(而非變數),因此要求的是物件必須具有AbstractFactory、 Part之公開方法(無論是「哪一種」物件),例如以下是Python的Abstract Factory實現範例:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def paint(self, factory):
point = factory.getPoint()
corner = factory.getCorner()
corner.leftUp()
point.line(self.width - 2)
corner.rightUp()
print()
for i in range(self.height - 2):
point.line(self.width)
print()
corner.leftDown()
point.line(self.width - 2);
corner.rightDown();
print()
class Dot:
def line(self, width):
for i in range(width):
print("-", end="")
class Sharp:
def leftUp(self):
print("#", end="")
def rightUp(self):
print("#", end="")
def leftDown(self):
print("#", end="")
def rightDown(self):
print("#", end="")
class DotSharpFactory:
def getPoint(self):
return Dot()
def getCorner(self):
return Sharp()
rect = Rectangle(20, 10)
rect.paint(DotSharpFactory())
AbstractFactory這個名詞是從的建立可抽換的一組 物件角度來看這個模式,如果將焦點放 在使用抽象工廠物件的方法上,因為方法定義了一個樣版流程,流程中真正需要實際物件運作的部份,則呼叫callback物件(工廠物件)來建立,所以從流 程的觀點來看,又稱之為Template-callback模式。例 如在範例的paint()方法中定義了繪製的流程,真正繪製的物件則是透過callback物件(工廠物件)來建立。