抽象工廠模式
抽象工廠模式是所有形態(tài)的工廠模式中最為抽象和最具一般性的一種形態(tài)启泣。
抽象工廠模式是指當(dāng)有多個(gè)抽象角色時(shí),使用的一種工廠模式头镊。抽象工廠模式可以向客戶端提供一個(gè)接口磷雇,使客戶端在不必指定產(chǎn)品的具體的情況下毛好,創(chuàng)建多個(gè)產(chǎn)品族中的產(chǎn)品對(duì)象。根據(jù)里氏替換原則苛秕,任何接受父類型的地方肌访,都應(yīng)當(dāng)能夠接受子類型。因此艇劫,實(shí)際上系統(tǒng)所需要的吼驶,僅僅是類型與這些抽象產(chǎn)品角色相同的一些實(shí)例,而不是這些抽象產(chǎn)品的實(shí)例店煞。換言之蟹演,也就是這些抽象產(chǎn)品的具體子類的實(shí)例。工廠類負(fù)責(zé)創(chuàng)建抽象產(chǎn)品的具體子類的實(shí)例顷蟀。
抽象工廠的定義
為創(chuàng)建一組相關(guān)或相互依賴的對(duì)象提供一個(gè)接口酒请,而且無需指定他們的具體類。
抽象工廠實(shí)例代碼
創(chuàng)建Shape
和 Color
接口和實(shí)現(xiàn)這些接口的實(shí)體類衩椒。下一步是創(chuàng)建抽象工廠類 AbstractFactory
蚌父。接著定義工廠類ShapeFactory
和ColorFactory
,這兩個(gè)工廠類都是擴(kuò)展了 AbstractFactory
毛萌。然后創(chuàng)建一個(gè)工廠創(chuàng)造器/生成器類FactoryProducer
苟弛。
AbstractFactoryPatternDemo
,我們的演示類使用FactoryProducer
來獲取AbstractFactory
對(duì)象阁将。它將向 AbstractFactory
傳遞形狀信息 Shape(CIRCLE / RECTANGLE / SQUARE)膏秫,以便獲取它所需對(duì)象的類型。同時(shí)它還向 AbstractFactory 傳遞顏色信息 Color(RED / GREEN / BLUE)做盅,以便獲取它所需對(duì)象的類型缤削。
1.為形狀創(chuàng)建一個(gè)接口。
public interface Shape {
void draw();
}
2.創(chuàng)建實(shí)現(xiàn)接口的實(shí)體類
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.為顏色創(chuàng)建一個(gè)接口
Color.java
public interface Color {
void fill();
}
4.創(chuàng)建實(shí)現(xiàn)接口的實(shí)體類
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 對(duì)象創(chuàng)建抽象類來獲取工廠
AbstractFactory.java
public abstract class AbstractFactory {
public abstract Color getColor(String color);
public abstract Shape getShape(String shape) ;
}
6.創(chuàng)建擴(kuò)展了 AbstractFactory 的工廠類吹榴,基于給定的信息生成實(shí)體類的對(duì)象
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.創(chuàng)建一個(gè)工廠創(chuàng)造器/生成器類亭敢,通過傳遞形狀或顏色信息來獲取工廠
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,通過傳遞類型信息來獲取實(shí)體類的對(duì)象
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
// 獲取形狀工廠
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
// 獲取形狀為 Circle 的對(duì)象
Shape shape1 = shapeFactory.getShape("CIRCLE");
// 調(diào)用 Circle 的 draw 方法
shape1.draw();
// 獲取形狀為 Rectangle 的對(duì)象
Shape shape2 = shapeFactory.getShape("RECTANGLE");
// 調(diào)用 Rectangle 的 draw 方法
shape2.draw();
// 獲取形狀為 Square 的對(duì)象
Shape shape3 = shapeFactory.getShape("SQUARE");
// 調(diào)用 Square 的 draw 方法
shape3.draw();
// 獲取顏色工廠
AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
// 獲取顏色為 Red 的對(duì)象
Color color1 = colorFactory.getColor("RED");
// 調(diào)用 Red 的 fill 方法
color1.fill();
// 獲取顏色為 Green 的對(duì)象
Color color2 = colorFactory.getColor("Green");
// 調(diào)用 Green 的 fill 方法
color2.fill();
// 獲取顏色為 Blue 的對(duì)象
Color color3 = colorFactory.getColor("BLUE");
// 調(diào)用 Blue 的 fill 方法
color3.fill();
}
}
9.執(zhí)行上面代碼图筹,輸出結(jié)果
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
抽象工廠模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
當(dāng)一個(gè)產(chǎn)品族中的多個(gè)對(duì)象被設(shè)計(jì)成一起工作時(shí)帅刀,它能保證客戶端始終只使用同一個(gè)產(chǎn)品族中的對(duì)象。
缺點(diǎn)
產(chǎn)品族擴(kuò)展非常困難远剩,要增加一個(gè)系列的某一產(chǎn)品扣溺,既要在抽象的 Creator 里加代碼,又要在具體的里面加代碼瓜晤。
抽象工廠模式使用場景
1锥余、QQ 的一鍵換皮膚,一下子就是換一整套皮膚痢掠。
2驱犹、生成不同操作系統(tǒng)的程序嘲恍。
使用的注意事項(xiàng)
產(chǎn)品族難擴(kuò)展,產(chǎn)品等級(jí)易擴(kuò)展。
產(chǎn)品族
上面抽象工廠模式中有提到產(chǎn)品族着绷,什么是產(chǎn)品族呢蛔钙?產(chǎn)品族
是指位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中,功能相關(guān)聯(lián)的產(chǎn)品組成的家族荠医。一般是位于不同的等級(jí)結(jié)構(gòu)中的相同位置上吁脱。顯然,每一個(gè)產(chǎn)品族中含有產(chǎn)品的數(shù)目彬向,與產(chǎn)品等級(jí)結(jié)構(gòu)的數(shù)目是相等的兼贡,形成一個(gè)二維的坐標(biāo)系,水平坐標(biāo)是產(chǎn)品等級(jí)結(jié)構(gòu)娃胆,縱坐標(biāo)是產(chǎn)品族遍希。叫做相圖。
當(dāng)有多個(gè)不同的等級(jí)結(jié)構(gòu)的產(chǎn)品時(shí)里烦,如果使用工廠方法模式就勢必要使用多個(gè)獨(dú)立的工廠等級(jí)結(jié)構(gòu)來對(duì)付這些產(chǎn)品的等級(jí)結(jié)構(gòu)凿蒜。如果這些產(chǎn)品等級(jí)結(jié)構(gòu)是平行的,會(huì)導(dǎo)致多個(gè)平行的工廠等級(jí)結(jié)構(gòu)胁黑。
抽象工廠模式使用同一個(gè) 工廠等級(jí)結(jié)構(gòu)負(fù)責(zé)這些不同產(chǎn)品等級(jí)結(jié)構(gòu)產(chǎn)品對(duì)象的創(chuàng)建废封。
對(duì)于每一個(gè)產(chǎn)品族,都有一個(gè)具體工廠丧蘸。而每一個(gè)具體工廠創(chuàng)建屬于同一個(gè)產(chǎn)品族漂洋,但是分屬于不同等級(jí)結(jié)構(gòu)的產(chǎn)品。
通過引進(jìn)抽象工廠模式力喷,可以處理具有相同(或者相似)等級(jí)結(jié)構(gòu)的多個(gè)產(chǎn)品族中的產(chǎn)品對(duì)象的創(chuàng)建問題刽漂。
由于每個(gè)具體工廠角色都需要負(fù)責(zé)兩個(gè)不同等級(jí)結(jié)構(gòu)的產(chǎn)品對(duì)象的創(chuàng)建,因此每個(gè)工廠角色都需要提供兩個(gè)工廠方法弟孟,分別用于創(chuàng)建兩個(gè)等級(jí)結(jié)構(gòu)的產(chǎn)品贝咙。既然每個(gè)具體工廠角色都需要實(shí)現(xiàn)這兩個(gè)工廠方法,所以具有一般性拂募,不妨抽象出來颈畸,移動(dòng)到抽象工廠角色中加以聲明。