抽象工廠模式
抽象工廠模式是所有形態的工廠模式中最為抽象和最具一般性的一種形態。
抽象工廠模式是指當有多個抽象角色時,使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個接口,使客戶端在不必指定產品的具體的情況下,創建多個產品族中的產品對象。根據里氏替換原則,任何接受父類型的地方,都應當能夠接受子類型。因此,實際上系統所需要的,僅僅是類型與這些抽象產品角色相同的一些實例,而不是這些抽象產品的實例。換言之,也就是這些抽象產品的具體子類的實例。工廠類負責創建抽象產品的具體子類的實例。
抽象工廠的定義
為創建一組相關或相互依賴的對象提供一個接口,而且無需指定他們的具體類。
抽象工廠實例代碼
創建Shape
和 Color
接口和實現這些接口的實體類。下一步是創建抽象工廠類 AbstractFactory
。接著定義工廠類ShapeFactory
和ColorFactory
,這兩個工廠類都是擴展了 AbstractFactory
。然后創建一個工廠創造器/生成器類FactoryProducer
。
AbstractFactoryPatternDemo
,我們的演示類使用FactoryProducer
來獲取AbstractFactory
對象。它將向 AbstractFactory
傳遞形狀信息 Shape(CIRCLE / RECTANGLE / SQUARE),以便獲取它所需對象的類型。同時它還向 AbstractFactory 傳遞顏色信息 Color(RED / GREEN / BLUE),以便獲取它所需對象的類型。
1.為形狀創建一個接口。
public interface Shape {
void draw();
}
2.創建實現接口的實體類
Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
Square.java
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
3.為顏色創建一個接口
Color.java
public interface Color {
void fill();
}
4.創建實現接口的實體類
Red.java
public class Red implements Color {
@Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
Green.java
public class Green implements Color {
@Override
public void fill() {
System.out.println("Inside Green::fill() method.");
}
}
Blue.java
public class Blue implements Color {
@Override
public void fill() {
System.out.println("Inside Blue::fill() method.");
}
}
5.為 Color 和 Shape 對象創建抽象類來獲取工廠
AbstractFactory.java
public abstract class AbstractFactory {
public abstract Color getColor(String color);
public abstract Shape getShape(String shape) ;
}
6.創建擴展了 AbstractFactory 的工廠類,基于給定的信息生成實體類的對象
ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
@Override
public Color getColor(String color) {
return null;
}
}
ColorFactory.java
public class ColorFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
return null;
}
@Override
Color getColor(String color) {
if(color == null){
return null;
}
if(color.equalsIgnoreCase("RED")){
return new Red();
} else if(color.equalsIgnoreCase("GREEN")){
return new Green();
} else if(color.equalsIgnoreCase("BLUE")){
return new Blue();
}
return null;
}
}
7.創建一個工廠創造器/生成器類,通過傳遞形狀或顏色信息來獲取工廠
FactoryProducer.java
public class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("SHAPE")){
return new ShapeFactory();
} else if(choice.equalsIgnoreCase("COLOR")){
return new ColorFactory();
}
return null;
}
}
8.使用 FactoryProducer 來獲取 AbstractFactory,通過傳遞類型信息來獲取實體類的對象
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
// 獲取形狀工廠
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
// 獲取形狀為 Circle 的對象
Shape shape1 = shapeFactory.getShape("CIRCLE");
// 調用 Circle 的 draw 方法
shape1.draw();
// 獲取形狀為 Rectangle 的對象
Shape shape2 = shapeFactory.getShape("RECTANGLE");
// 調用 Rectangle 的 draw 方法
shape2.draw();
// 獲取形狀為 Square 的對象
Shape shape3 = shapeFactory.getShape("SQUARE");
// 調用 Square 的 draw 方法
shape3.draw();
// 獲取顏色工廠
AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
// 獲取顏色為 Red 的對象
Color color1 = colorFactory.getColor("RED");
// 調用 Red 的 fill 方法
color1.fill();
// 獲取顏色為 Green 的對象
Color color2 = colorFactory.getColor("Green");
// 調用 Green 的 fill 方法
color2.fill();
// 獲取顏色為 Blue 的對象
Color color3 = colorFactory.getColor("BLUE");
// 調用 Blue 的 fill 方法
color3.fill();
}
}
9.執行上面代碼,輸出結果
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
抽象工廠模式的優缺點
優點
當一個產品族中的多個對象被設計成一起工作時,它能保證客戶端始終只使用同一個產品族中的對象。
缺點
產品族擴展非常困難,要增加一個系列的某一產品,既要在抽象的 Creator 里加代碼,又要在具體的里面加代碼。
抽象工廠模式使用場景
1、QQ 的一鍵換皮膚,一下子就是換一整套皮膚。
2、生成不同操作系統的程序。
使用的注意事項
產品族難擴展,產品等級易擴展。
產品族
上面抽象工廠模式中有提到產品族,什么是產品族呢?產品族
是指位于不同產品等級結構中,功能相關聯的產品組成的家族。一般是位于不同的等級結構中的相同位置上。顯然,每一個產品族中含有產品的數目,與產品等級結構的數目是相等的,形成一個二維的坐標系,水平坐標是產品等級結構,縱坐標是產品族。叫做相圖。
當有多個不同的等級結構的產品時,如果使用工廠方法模式就勢必要使用多個獨立的工廠等級結構來對付這些產品的等級結構。如果這些產品等級結構是平行的,會導致多個平行的工廠等級結構。
抽象工廠模式使用同一個 工廠等級結構負責這些不同產品等級結構產品對象的創建。
對于每一個產品族,都有一個具體工廠。而每一個具體工廠創建屬于同一個產品族,但是分屬于不同等級結構的產品。
通過引進抽象工廠模式,可以處理具有相同(或者相似)等級結構的多個產品族中的產品對象的創建問題。
由于每個具體工廠角色都需要負責兩個不同等級結構的產品對象的創建,因此每個工廠角色都需要提供兩個工廠方法,分別用于創建兩個等級結構的產品。既然每個具體工廠角色都需要實現這兩個工廠方法,所以具有一般性,不妨抽象出來,移動到抽象工廠角色中加以聲明。