上一篇已經介紹過的 Factory Pattern 可以將建立實例的程式碼抽取出來, 並可以提供絡不同的物件使用。Abstract Factory Pattern 其實和 Factory Pattern 很相似,但 Abstract Factory 比較偏向建立同一系統的物件。
同一系列的意思是彼此的物件有一定的關連,例如: 輪子、引擎、車架、方向盤、儀標板等等。 這些都是組成車子的組件,這些組件亦由可以由不同廠商去開發,Abstract Factory 扮演角色就是廠商。 更改廠商,就可以建立不同樣式的車子。
看看以下例子應該有助你明白這個模式:
公司要開發一款迷宮遊戲,建立迷宮的組件有:『牆壁』、『門』和『道路』。 遊戲在不同的關卡會顯示不同風格的迷宮,首先要將做出組件的介面和建立一個工廠介面。
組件介面:
(Component.java) download package component ;
public interface Component {
public void draw ();
}
(Door.java) download package component ;
public interface Door extends Component {
}
(Wall.java) download package component ;
public interface Wall extends Component {
}
(Road.java) download package component ;
public interface Road extends Component {
}
(Labyrinth.java) download package component ;
import java.util.Random ;
import factory.LabyrinthComponentFactory ;
public class Labyrinth implements Component {
private LabyrinthComponentFactory labyrinthFactory ;
public Labyrinth ( LabyrinthComponentFactory labyrinthFactory ) {
this . labyrinthFactory = labyrinthFactory ;
}
@Override
public void draw () {
Random random = new Random ();
for ( int i = 0 ; i < 10 ; i ++) {
switch ( random . nextInt ( 15 )) {
case 0 :
labyrinthFactory . createDoor (). draw ();
break ;
case 1 :
case 2 :
case 3 :
case 4 :
case 5 :
labyrinthFactory . createRoad (). draw ();
break ;
default :
labyrinthFactory . createWall (). draw ();
break ;
}
}
}
}
藍色風格的組件:
(BlueDoor.java) download package component . blue ;
import component.Door ;
public class BlueDoor implements Door {
@Override
public void draw () {
System . out . println ( "Blue Door" );
}
}
(BlueWall.java) download package component . blue ;
import component.Wall ;
public class BlueWall implements Wall {
@Override
public void draw () {
System . out . println ( "Blue Wall" );
}
}
(BlueRoad.java) download package component . blue ;
import component.Road ;
public class BlueRoad implements Road {
@Override
public void draw () {
System . out . println ( "Blue Road" );
}
}
綠色風格的組件:
(GreenDoor.java) download package component . green ;
import component.Door ;
public class GreenDoor implements Door {
@Override
public void draw () {
System . out . println ( "Green Door" );
}
}
(GreenWall.java) download package component . green ;
import component.Wall ;
public class GreenWall implements Wall {
@Override
public void draw () {
System . out . println ( "Green Wall" );
}
}
(GreenRoad.java) download package component . green ;
import component.Road ;
public class GreenRoad implements Road {
@Override
public void draw () {
System . out . println ( "Green Road" );
}
}
工廠介面:
(LabyrinthComponentFactory.java) download package factory ;
import component.Door ;
import component.Road ;
import component.Wall ;
public interface LabyrinthComponentFactory {
public Wall createWall ();
public Door createDoor ();
public Road createRoad ();
}
(BlueStyleLabyrinthComponentFactory.java) download package factory ;
import component.Door ;
import component.Road ;
import component.Wall ;
import component.blue.BlueDoor ;
import component.blue.BlueRoad ;
import component.blue.BlueWall ;
public class BlueStyleLabyrinthComponentFactory implements
LabyrinthComponentFactory {
@Override
public Wall createWall () {
return new BlueWall ();
}
@Override
public Door createDoor () {
return new BlueDoor ();
}
@Override
public Road createRoad () {
return new BlueRoad ();
}
}
(GreenStyleLabyrinthComponentFactory.java) download package factory ;
import component.Door ;
import component.Road ;
import component.Wall ;
import component.green.GreenDoor ;
import component.green.GreenRoad ;
import component.green.GreenWall ;
public class GreenStyleLabyrinthComponentFactory implements
LabyrinthComponentFactory {
@Override
public Wall createWall () {
return new GreenWall ();
}
@Override
public Door createDoor () {
return new GreenDoor ();
}
@Override
public Road createRoad () {
return new GreenRoad ();
}
}
(Main.java) download import component.Labyrinth ;
import factory.BlueStyleLabyrinthComponentFactory ;
import factory.GreenStyleLabyrinthComponentFactory ;
import factory.LabyrinthComponentFactory ;
public class Main {
public static void main ( String [] args ) {
LabyrinthComponentFactory blueStyleLabyrinthComponentFactory = new BlueStyleLabyrinthComponentFactory ();
LabyrinthComponentFactory greenStyleLabyrinthComponentFactory = new GreenStyleLabyrinthComponentFactory ();
Labyrinth blueStyleLabyrinth = new Labyrinth ( blueStyleLabyrinthComponentFactory );
Labyrinth greenStyleLabyrinth = new Labyrinth ( greenStyleLabyrinthComponentFactory );
blueStyleLabyrinth . draw ();
System . out . println ( "------------------" );
greenStyleLabyrinth . draw ();
}
}
執行結果 Blue Road
Blue Road
Blue Road
Blue Wall
Blue Road
Blue Door
Blue Wall
Blue Road
Blue Road
Blue Road
------------------
Green Wall
Green Wall
Green Wall
Green Road
Green Wall
Green Wall
Green Wall
Green Road
Green Wall
Green Road
在建立 Labyrinth
時,只需將工廠交給 Labyrinth
就可以建立不同風格的迷宮。
要新增更多風格的組件,只需要建立相對應的工廠就可以了,完全不需要改動 Labyrinth.draw
的程式碼。
不過 Abstract Factory 有一個缺點,如果你要新増一個原先不存在的組件,例如加一個『陷阱』, 你便需要更改 LabyrinthFactory
這個介面。
以下的圖片是描述 Abstract Factory Pattern 的 Class Diagram。(From Wiki)